aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS35
-rw-r--r--Makefile2
-rw-r--r--Makefile.common1
-rw-r--r--NEWS42
-rw-r--r--README8
-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-factory.cpp42
-rw-r--r--backends/fs/palmos/palmos-fs.cpp212
-rw-r--r--backends/fs/psp/psp-stream.cpp14
-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.mk48
-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_aeroplayer.h65
-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/formCards.h33
-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.build71
-rw-r--r--backends/platform/android/android.cpp161
-rw-r--r--backends/platform/android/android.mk9
-rw-r--r--backends/platform/android/module.mk31
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVM.java130
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java24
-rw-r--r--backends/platform/android/org/inodes/gus/scummvm/Unpacker.java4
-rw-r--r--backends/platform/android/scummvm-android-themeengine.patch135
-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/makefile199
-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.cpp557
-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/fat/gba_nds_fat.c12
-rw-r--r--backends/platform/ds/arm9/source/fat/io_nmmc.c10
-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/module.mk76
-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.sh9
-rwxr-xr-xbackends/platform/gp2xwiz/build/bundle.sh54
-rwxr-xr-xbackends/platform/gp2xwiz/build/scummvm-gdb.gpe16
-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.ps22
-rw-r--r--backends/platform/ps2/module.mk9
-rw-r--r--backends/platform/psp/Makefile13
-rw-r--r--backends/platform/psp/README.PSP2
-rw-r--r--backends/platform/psp/README.PSP.in2
-rw-r--r--backends/platform/psp/audio.cpp45
-rw-r--r--backends/platform/psp/audio.h10
-rw-r--r--backends/platform/psp/display_client.cpp15
-rw-r--r--backends/platform/psp/display_manager.cpp48
-rw-r--r--backends/platform/psp/display_manager.h30
-rw-r--r--backends/platform/psp/memory.cpp457
-rw-r--r--backends/platform/psp/memory.h61
-rw-r--r--backends/platform/psp/module.mk13
-rw-r--r--backends/platform/psp/mp3.cpp6
-rw-r--r--backends/platform/psp/mp3.h2
-rw-r--r--backends/platform/psp/osys_psp.cpp102
-rw-r--r--backends/platform/psp/osys_psp.h11
-rw-r--r--backends/platform/psp/powerman.cpp352
-rw-r--r--backends/platform/psp/powerman.h75
-rw-r--r--backends/platform/psp/psp_main.cpp11
-rw-r--r--backends/platform/psp/psploader.cpp141
-rw-r--r--backends/platform/psp/rtc.cpp87
-rw-r--r--backends/platform/psp/rtc.h (renamed from backends/platform/PalmOS/Src/cd_msa.h)66
-rw-r--r--backends/platform/psp/tests.cpp565
-rw-r--r--backends/platform/psp/tests.h (renamed from backends/platform/PalmOS/Src/init_palmos.h)26
-rw-r--r--backends/platform/psp/thread.cpp215
-rw-r--r--backends/platform/psp/thread.h68
-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/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/psp/psp-provider.cpp8
-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.cpp14
-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-xconfigure578
-rw-r--r--dists/android/AndroidManifest.xml58
-rw-r--r--dists/android/AndroidManifest.xml.in58
-rwxr-xr-x[-rw-r--r--]dists/android/mkmanifest.pl1
-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/engine-data/kyra.datbin353834 -> 355277 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/cine.cpp18
-rw-r--r--engines/cine/cine.h2
-rw-r--r--engines/cine/detection.cpp499
-rw-r--r--engines/cine/detection_tables.h513
-rw-r--r--engines/cine/gfx.cpp19
-rw-r--r--engines/cine/gfx.h4
-rw-r--r--engines/cine/saveload.cpp12
-rw-r--r--engines/cine/saveload.h2
-rw-r--r--engines/cine/various.cpp2
-rw-r--r--engines/cruise/cruise.cpp4
-rw-r--r--engines/cruise/cruise_main.cpp10
-rw-r--r--engines/cruise/decompiler.cpp2
-rw-r--r--engines/cruise/detection.cpp6
-rw-r--r--engines/cruise/vars.cpp4
-rw-r--r--engines/cruise/vars.h5
-rw-r--r--engines/dialogs.cpp27
-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/detection.cpp4995
-rw-r--r--engines/gob/detection_tables.h5013
-rw-r--r--engines/gob/gob.cpp13
-rw-r--r--engines/gob/inter_playtoons.cpp2
-rw-r--r--engines/gob/inter_v1.cpp11
-rw-r--r--engines/gob/mult_v2.cpp2
-rw-r--r--engines/gob/videoplayer.cpp2
-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.h1192
-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.cpp4
-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.cpp4252
-rw-r--r--engines/kyra/staticres.cpp864
-rw-r--r--engines/kyra/staticres_lol.cpp882
-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.cpp155
-rw-r--r--engines/m4/animation.h18
-rw-r--r--engines/m4/assets.cpp86
-rw-r--r--engines/m4/assets.h23
-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.cpp25
-rw-r--r--engines/m4/font.h8
-rw-r--r--engines/m4/globals.cpp33
-rw-r--r--engines/m4/globals.h18
-rw-r--r--engines/m4/graphics.cpp231
-rw-r--r--engines/m4/graphics.h25
-rw-r--r--engines/m4/hotspot.cpp7
-rw-r--r--engines/m4/hotspot.h4
-rw-r--r--engines/m4/m4.cpp42
-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.cpp93
-rw-r--r--engines/m4/mads_anim.h3
-rw-r--r--engines/m4/mads_logic.cpp304
-rw-r--r--engines/m4/mads_logic.h18
-rw-r--r--engines/m4/mads_menus.cpp21
-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.cpp677
-rw-r--r--engines/m4/mads_scene.h107
-rw-r--r--engines/m4/mads_views.cpp524
-rw-r--r--engines/m4/mads_views.h119
-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.h2
-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.cpp41
-rw-r--r--engines/mohawk/console.h1
-rw-r--r--engines/mohawk/detection.cpp883
-rw-r--r--engines/mohawk/detection_tables.h1030
-rw-r--r--engines/mohawk/dialogs.cpp17
-rw-r--r--engines/mohawk/graphics.cpp41
-rw-r--r--engines/mohawk/resource.cpp2
-rw-r--r--engines/mohawk/riven.cpp101
-rw-r--r--engines/mohawk/riven.h12
-rw-r--r--engines/mohawk/riven_external.cpp200
-rw-r--r--engines/mohawk/riven_external.h1
-rw-r--r--engines/mohawk/riven_saveload.cpp67
-rw-r--r--engines/mohawk/riven_saveload.h3
-rw-r--r--engines/mohawk/riven_scripts.cpp68
-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.cpp4
-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.cpp1160
-rw-r--r--engines/sci/console.h21
-rw-r--r--engines/sci/debug.h7
-rw-r--r--engines/sci/decompressor.cpp16
-rw-r--r--engines/sci/detection.cpp151
-rw-r--r--engines/sci/detection_tables.h1225
-rw-r--r--engines/sci/engine/features.cpp194
-rw-r--r--engines/sci/engine/features.h16
-rw-r--r--engines/sci/engine/game.cpp169
-rw-r--r--engines/sci/engine/gc.cpp163
-rw-r--r--engines/sci/engine/gc.h15
-rw-r--r--engines/sci/engine/kernel.cpp1252
-rw-r--r--engines/sci/engine/kernel.h255
-rw-r--r--engines/sci/engine/kernel32.cpp823
-rw-r--r--engines/sci/engine/kernel_tables.h1031
-rw-r--r--engines/sci/engine/kevent.cpp45
-rw-r--r--engines/sci/engine/kfile.cpp904
-rw-r--r--engines/sci/engine/kgraphics.cpp970
-rw-r--r--engines/sci/engine/klists.cpp417
-rw-r--r--engines/sci/engine/kmath.cpp64
-rw-r--r--engines/sci/engine/kmenu.cpp8
-rw-r--r--engines/sci/engine/kmisc.cpp179
-rw-r--r--engines/sci/engine/kmovement.cpp159
-rw-r--r--engines/sci/engine/kparse.cpp15
-rw-r--r--engines/sci/engine/kpathing.cpp284
-rw-r--r--engines/sci/engine/kscripts.cpp122
-rw-r--r--engines/sci/engine/ksound.cpp106
-rw-r--r--engines/sci/engine/kstring.cpp220
-rw-r--r--engines/sci/engine/kvideo.cpp303
-rw-r--r--engines/sci/engine/message.cpp20
-rw-r--r--engines/sci/engine/savegame.cpp612
-rw-r--r--engines/sci/engine/savegame.h8
-rw-r--r--engines/sci/engine/script.cpp794
-rw-r--r--engines/sci/engine/script.h359
-rw-r--r--engines/sci/engine/scriptdebug.cpp221
-rw-r--r--engines/sci/engine/seg_manager.cpp450
-rw-r--r--engines/sci/engine/seg_manager.h129
-rw-r--r--engines/sci/engine/segment.cpp512
-rw-r--r--engines/sci/engine/segment.h250
-rw-r--r--engines/sci/engine/selector.cpp51
-rw-r--r--engines/sci/engine/selector.h136
-rw-r--r--engines/sci/engine/state.cpp130
-rw-r--r--engines/sci/engine/state.h87
-rw-r--r--engines/sci/engine/static_selectors.cpp154
-rw-r--r--engines/sci/engine/vm.cpp1181
-rw-r--r--engines/sci/engine/vm.h375
-rw-r--r--engines/sci/engine/vm_types.h1
-rw-r--r--engines/sci/engine/workarounds.cpp426
-rw-r--r--engines/sci/engine/workarounds.h106
-rw-r--r--engines/sci/event.cpp82
-rw-r--r--engines/sci/event.h58
-rw-r--r--engines/sci/graphics/animate.cpp557
-rw-r--r--engines/sci/graphics/animate.h20
-rw-r--r--engines/sci/graphics/cache.cpp6
-rw-r--r--engines/sci/graphics/cache.h2
-rw-r--r--engines/sci/graphics/compare.cpp104
-rw-r--r--engines/sci/graphics/compare.h6
-rw-r--r--engines/sci/graphics/controls.cpp7
-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.cpp510
-rw-r--r--engines/sci/graphics/frameout.h39
-rw-r--r--engines/sci/graphics/gui.cpp139
-rw-r--r--engines/sci/graphics/gui.h91
-rw-r--r--engines/sci/graphics/gui32.cpp83
-rw-r--r--engines/sci/graphics/helpers.h1
-rw-r--r--engines/sci/graphics/maciconbar.cpp1
-rw-r--r--engines/sci/graphics/menu.cpp113
-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.cpp144
-rw-r--r--engines/sci/graphics/paint16.h29
-rw-r--r--engines/sci/graphics/paint32.cpp7
-rw-r--r--engines/sci/graphics/paint32.h3
-rw-r--r--engines/sci/graphics/palette.cpp496
-rw-r--r--engines/sci/graphics/palette.h56
-rw-r--r--engines/sci/graphics/picture.cpp238
-rw-r--r--engines/sci/graphics/picture.h8
-rw-r--r--engines/sci/graphics/portrait.cpp12
-rw-r--r--engines/sci/graphics/portrait.h5
-rw-r--r--engines/sci/graphics/ports.cpp181
-rw-r--r--engines/sci/graphics/ports.h15
-rw-r--r--engines/sci/graphics/robot.cpp42
-rw-r--r--engines/sci/graphics/robot.h7
-rw-r--r--engines/sci/graphics/screen.cpp155
-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.mk11
-rw-r--r--engines/sci/parser/grammar.cpp44
-rw-r--r--engines/sci/parser/said.cpp2831
-rw-r--r--engines/sci/parser/said.y839
-rw-r--r--engines/sci/parser/vocabulary.cpp382
-rw-r--r--engines/sci/parser/vocabulary.h39
-rw-r--r--engines/sci/resource.cpp970
-rw-r--r--engines/sci/resource.h371
-rw-r--r--engines/sci/resource_audio.cpp336
-rw-r--r--engines/sci/resource_intern.h219
-rw-r--r--engines/sci/sci.cpp467
-rw-r--r--engines/sci/sci.h186
-rw-r--r--engines/sci/sound/audio.cpp100
-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/iterator/core.cpp1013
-rw-r--r--engines/sci/sound/iterator/core.h209
-rw-r--r--engines/sci/sound/iterator/iterator.cpp1686
-rw-r--r--engines/sci/sound/iterator/iterator.h326
-rw-r--r--engines/sci/sound/iterator/iterator_internal.h276
-rw-r--r--engines/sci/sound/iterator/songlib.cpp189
-rw-r--r--engines/sci/sound/iterator/songlib.h171
-rw-r--r--engines/sci/sound/iterator/test-iterator.cpp423
-rw-r--r--engines/sci/sound/midiparser_sci.cpp664
-rw-r--r--engines/sci/sound/midiparser_sci.h40
-rw-r--r--engines/sci/sound/music.cpp269
-rw-r--r--engines/sci/sound/music.h62
-rw-r--r--engines/sci/sound/soundcmd.cpp973
-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.cpp4
-rw-r--r--engines/sci/video/vmd_decoder.h2
-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.h47
-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/testbed/config.cpp12
-rw-r--r--engines/testbed/detection.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/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--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/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.cpp4
-rw-r--r--graphics/video/avi_decoder.h2
-rw-r--r--graphics/video/codecs/cinepak.cpp5
-rw-r--r--graphics/video/codecs/qdm2.cpp159
-rw-r--r--graphics/video/codecs/qdm2.h2
-rw-r--r--graphics/video/coktelvideo/coktelvideo.cpp12
-rw-r--r--graphics/video/coktelvideo/coktelvideo.h16
-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.h4
-rw-r--r--graphics/video/qt_decoder.cpp12
-rw-r--r--graphics/video/qt_decoder.h2
-rw-r--r--graphics/video/smk_decoder.cpp4
-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.cpp13
-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.h36
-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.inc1572
-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.zipbin52242 -> 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.zipbin158233 -> 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.cpp186
-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.h (renamed from backends/fs/palmos/palmos-fs-factory.h)49
-rw-r--r--sound/decoders/mp3.cpp6
-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.cpp26
-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.h (renamed from backends/platform/PalmOS/Src/args.h)44
-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.cpp1562
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_audio.h176
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_euphony.cpp903
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_euphony.h185
-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.cpp1510
-rw-r--r--sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h176
-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.cpp5
-rw-r--r--tools/create_kyradat/create_kyradat.h2
-rw-r--r--tools/create_kyradat/games.cpp2
-rw-r--r--tools/create_kyradat/tables.cpp7
-rw-r--r--tools/create_msvc/create_msvc.cpp100
-rwxr-xr-xtools/credits.pl42
-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
950 files changed, 168254 insertions, 58228 deletions
diff --git a/AUTHORS b/AUTHORS
index 28d71b3698..76ff47e9db 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -190,9 +190,6 @@ ScummVM Team
Nintendo DS:
Neil Millstone
- PalmOS:
- Chris Apers
-
PocketPC / WinCE:
Nicolas Bacca - (retired)
Kostas Nakos
@@ -256,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
@@ -318,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
@@ -395,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/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..14d220f990 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -28,6 +28,7 @@ MODULES += \
engines \
graphics \
common \
+ po
ifdef USE_MT32EMU
MODULES += sound/softsynth/mt32
diff --git a/NEWS b/NEWS
index 32fe9a81c6..aac0b7f7e4 100644
--- a/NEWS
+++ b/NEWS
@@ -5,16 +5,50 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
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).
- General:
- - Switched to the "fast" DOSBox OPL emulator.
- - Fixed a crash in the rjp1 player code affecting the FOTAQ Amiga version.
-
1.1.2 (????-??-??)
Broken Sword 2
- Fixed missing speech in some cutscenes.
diff --git a/README b/README
index 3c97bbbbd7..c583cf994c 100644
--- a/README
+++ b/README
@@ -859,17 +859,13 @@ Supported platforms include (but are not limited to):
Nintendo DS
Nintendo Wii
OS/2
- PalmOS
PlayStation 2
PlayStation Portable
Symbian
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
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-factory.cpp b/backends/fs/palmos/palmos-fs-factory.cpp
deleted file mode 100644
index 97b3644205..0000000000
--- a/backends/fs/palmos/palmos-fs-factory.cpp
+++ /dev/null
@@ -1,42 +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 "backends/fs/palmos/palmos-fs-factory.h"
-#include "backends/fs/palmos/palmos-fs.cpp"
-
-DECLARE_SINGLETON(PalmOSFilesystemFactory)
-
-AbstractFSNode *PalmOSFilesystemFactory::makeRootFileNode() const {
- return new PalmOSFilesystemNode();
-}
-
-AbstractFSNode *PalmOSFilesystemFactory::makeCurrentDirectoryFileNode() const {
- return new PalmOSFilesystemNode();
-}
-
-AbstractFSNode *PalmOSFilesystemFactory::makeFileNodePath(const Common::String &path) const {
- return new PalmOSFilesystemNode(path);
-}
-#endif
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 83ff095aa8..67c73beeaa 100644
--- a/backends/fs/psp/psp-stream.cpp
+++ b/backends/fs/psp/psp-stream.cpp
@@ -81,10 +81,10 @@ PSPIoStream::PSPIoStream(const Common::String &path, bool writeMode)
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
+ 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
@@ -100,7 +100,7 @@ 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");
}
@@ -118,7 +118,7 @@ void *PSPIoStream::open() {
_cache = (char *)memalign(64, CACHE_SIZE);
}
- PowerMan.registerSuspend(this); // Register with the powermanager to be suspended
+ PowerMan.registerForSuspend(this); // Register with the powermanager to be suspended
PowerMan.endCriticalSection();
@@ -233,7 +233,7 @@ uint32 PSPIoStream::read(void *ptr, uint32 len) {
}
}
- if (PowerMan.beginCriticalSection() == PowerManager::Blocked)
+ if (PowerMan.beginCriticalSection())
PSP_DEBUG_PRINT_FUNC("Suspended\n");
@@ -309,7 +309,7 @@ inline bool PSPIoStream::isOffsetInCache(uint32 offset) {
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[0x%x]\n", _path.c_str(), len);
@@ -346,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);
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 59df56b468..e0a3f4c683 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 \
@@ -30,22 +22,54 @@ MODULE_OBJS := \
midi/timidity.o \
midi/dmedia.o \
midi/windows.o \
- plugins/dc/dc-provider.o \
plugins/posix/posix-provider.o \
plugins/sdl/sdl-provider.o \
plugins/win32/win32-provider.o \
- plugins/psp/psp-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
+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
+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_aeroplayer.h b/backends/platform/PalmOS/Src/cd_aeroplayer.h
deleted file mode 100644
index e661e06d52..0000000000
--- a/backends/platform/PalmOS/Src/cd_aeroplayer.h
+++ /dev/null
@@ -1,65 +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_AEROPLAYER_H
-#define CD_AEROPLAYER_H
-
-#include "cdaudio.h"
-#include "aeroplayer_public.h"
-
-class AeroCDPlayer : public CDAudio {
-public:
- AeroCDPlayer(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];
-
- 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;
-};
-
-#endif
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/formCards.h b/backends/platform/PalmOS/Src/launcher/forms/formCards.h
deleted file mode 100644
index 766c4793b9..0000000000
--- a/backends/platform/PalmOS/Src/launcher/forms/formCards.h
+++ /dev/null
@@ -1,33 +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 __FORMCARDS_H__
-#define __FORMCARDS_H__
-
-UInt16 parseCards();
-void CardSlotFormUpdate();
-void CardSlotCreateDirs();
-
-#endif
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
index fa56bfc180..1c407bd469 100644
--- a/backends/platform/android/README.build
+++ b/backends/platform/android/README.build
@@ -2,41 +2,38 @@ Building the ScummVM Android port
=================================
You will need these things to build:
-1. Android EGL headers and library
-2. Android SDK
-3. An arm-android-eabi GCC toolchain
+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.
-In detail:
-
-1. Android EGL headers and library
+(*) 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.
-You can build these from the full Android source, but it is far easier
-to just download the 3 Android EGL headers from here:
- http://android.git.kernel.org/?p=platform/frameworks/base.git;a=tree;f=opengl/include/EGL;hb=HEAD
- (copy them to a directory called "EGL" somewhere)
-... and grab libEGL.so off an existing phone/emulator:
- adb pull /system/lib/libEGL.so /tmp
+In detail:
-2. Android SDK
+1. Android SDK
-Download and install somewhere.
+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.
-3. arm-android-eabi GCC toolchain
+2. arm-*-linux-androideabi GCC toolchain
You have several choices for toolchains:
-- Use Google arm-eabi prebuilt toolchain.
+ - 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-android-eabi-foo" to
+of shell wrapper scripts that convert "arm-oe-linux-androideabi-foo" to
"arm-eabi-foo -mandroid".
For example, I use this script:
@@ -44,17 +41,24 @@ For example, I use this script:
exec arm-eabi-${0##*-} -mandroid -DANDROID "$@"
... and create a family of symlinks/hardlinks pointing to it called
-arm-android-eabi-gcc, arm-android-eabi-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-android-eabi-strip symlink to the tool
-directly.
+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-android-eabi toolchain from GCC source.
+ - Build your own arm-*-linux-androideabi toolchain from GCC source.
-This is lots of fun. I suggest my Android openembedded patches, see:
- http://wiki.github.com/anguslees/openembedded-android/
-(You just need to have lots of disk space and type a few commands)
-If you get stuck, ask
+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.
@@ -63,18 +67,21 @@ 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-android-eabi toolchain is in your $PATH
+ # You also want to ensure your arm-oe-linux-androideabi toolchain is in $PATH
export ANDROID_TOP=<root of built Android source>
- EGL_INC="-I<location of EGL/ header directory>"
- EGL_LIBS="-L<location of libEGL.so>"
-
- CPPFLAGS="$EGL_INC" \
- LDFLAGS="-g $EGL_LIBS" \
./configure --backend=android --host=android --enable-zlib #and any other flags
make scummvm.apk
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index a6258df554..f6af0fcff5 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -31,10 +31,6 @@
#if defined(ANDROID_BACKEND)
-#define ANDROID_VERSION_GE(major,minor) \
- (ANDROID_MAJOR_VERSION > (major) || \
- (ANDROID_MAJOR_VERSION == (major) && ANDROID_MINOR_VERSION >= (minor)))
-
#include <jni.h>
#include <string.h>
@@ -45,7 +41,6 @@
#include <GLES/gl.h>
#include <GLES/glext.h>
-#include <EGL/egl.h>
#include <android/log.h>
#include "common/archive.h"
@@ -78,6 +73,14 @@
#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;
@@ -162,20 +165,19 @@ private:
jmethodID MID_getPluginDirectories;
jmethodID MID_setupScummVMSurface;
jmethodID MID_destroyScummVMSurface;
+ jmethodID MID_swapBuffers;
int _screen_changeid;
- EGLDisplay _egl_display;
- EGLSurface _egl_surface;
- EGLint _egl_surface_width;
- EGLint _egl_surface_height;
+ 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;
- Common::Array<Common::Rect> _dirty_rects;
// Overlay layer
GLES4444Texture* _overlay_texture;
@@ -195,6 +197,7 @@ private:
pthread_t _timer_thread;
static void* timerThreadFunc(void* arg);
+ bool _enable_zoning;
bool _virtkeybd_on;
Common::SaveFileManager *_savefile;
@@ -217,6 +220,11 @@ public:
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);
@@ -297,8 +305,6 @@ public:
OSystem_Android::OSystem_Android(jobject am)
: _back_ptr(0),
- _egl_display(EGL_NO_DISPLAY),
- _egl_surface(EGL_NO_SURFACE),
_screen_changeid(0),
_force_redraw(false),
_game_texture(NULL),
@@ -307,6 +313,7 @@ OSystem_Android::OSystem_Android(jobject am)
_use_mouse_palette(false),
_show_mouse(false),
_show_overlay(false),
+ _enable_zoning(false),
_savefile(0),
_mixer(0),
_timer(0),
@@ -362,6 +369,7 @@ bool OSystem_Android::initJavaHooks(JNIEnv* env, jobject self) {
FIND_METHOD(getPluginDirectories, "()[Ljava/lang/String;");
FIND_METHOD(setupScummVMSurface, "()V");
FIND_METHOD(destroyScummVMSurface, "()V");
+ FIND_METHOD(swapBuffers, "()Z");
#undef FIND_METHOD
@@ -574,6 +582,7 @@ int OSystem_Android::getGraphicsMode() const {
}
void OSystem_Android::setupScummVMSurface() {
+ ENTER("setupScummVMSurface");
JNIEnv* env = JNU_GetEnv();
env->CallVoidMethod(_back_ptr, MID_setupScummVMSurface);
if (env->ExceptionCheck())
@@ -581,37 +590,8 @@ void OSystem_Android::setupScummVMSurface() {
// EGL set up with a new surface. Initialise OpenGLES context.
- _egl_display = eglGetCurrentDisplay();
- _egl_surface = eglGetCurrentSurface(EGL_DRAW);
-
- static bool log_version = true;
- if (log_version) {
- __android_log_print(ANDROID_LOG_INFO, LOG_TAG,
- "Using EGL %s (%s); GL %s/%s (%s)",
- eglQueryString(_egl_display, EGL_VERSION),
- eglQueryString(_egl_display, EGL_VENDOR),
- glGetString(GL_VERSION),
- glGetString(GL_RENDERER),
- glGetString(GL_VENDOR));
- log_version = false; // only log this once
- }
-
GLESTexture::initGLExtensions();
- if (!eglQuerySurface(_egl_display, _egl_surface,
- EGL_WIDTH, &_egl_surface_width) ||
- !eglQuerySurface(_egl_display, _egl_surface,
- EGL_HEIGHT, &_egl_surface_height)) {
- JNU_ThrowByName(env, "java/lang/RuntimeException",
- "Error fetching EGL surface width/height");
- return;
- }
- __android_log_print(ANDROID_LOG_INFO, LOG_TAG,
- "New surface is %dx%d",
- _egl_surface_width, _egl_surface_height);
-
- CHECK_GL_ERROR();
-
// Turn off anything that looks like 3D ;)
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
@@ -645,20 +625,18 @@ void OSystem_Android::setupScummVMSurface() {
_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();
-
- _force_redraw = true;
}
void OSystem_Android::destroyScummVMSurface() {
- _egl_surface = EGL_NO_SURFACE;
JNIEnv* env = JNU_GetEnv();
env->CallVoidMethod(_back_ptr, MID_destroyScummVMSurface);
// Can't use OpenGLES functions after this
@@ -676,7 +654,7 @@ void OSystem_Android::initSize(uint width, uint height,
_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. 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);
@@ -691,7 +669,7 @@ int16 OSystem_Android::getWidth() {
}
void OSystem_Android::setPalette(const byte* colors, uint start, uint num) {
- ENTER("setPalette(%p, %u, %u)", colors, start, num);
+ ENTER("setPalette(%p, %u, %u)", colors, start, num);
if (!_use_mouse_palette)
_setCursorPalette(colors, start, num);
@@ -739,8 +717,11 @@ void OSystem_Android::updateScreen() {
glPushMatrix();
- if (_shake_offset != 0) {
- // This is the only case where _game_texture doesn't
+ 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);
@@ -749,15 +730,29 @@ void OSystem_Android::updateScreen() {
glTranslatex(0, -_shake_offset << 16, 0);
}
- _game_texture->drawTexture(0, 0,
- _egl_surface_width, _egl_surface_height);
+ 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);
+ _egl_surface_width,
+ _egl_surface_height);
CHECK_GL_ERROR();
}
@@ -765,8 +760,8 @@ void OSystem_Android::updateScreen() {
glPushMatrix();
glTranslatex(-_mouse_hotspot.x << 16,
- -_mouse_hotspot.y << 16,
- 0);
+ -_mouse_hotspot.y << 16,
+ 0);
// Scale up ScummVM -> OpenGL (pixel) coordinates
int texwidth, texheight;
@@ -778,8 +773,8 @@ void OSystem_Android::updateScreen() {
texheight = getHeight();
}
glScalex(xdiv(_egl_surface_width, texwidth),
- xdiv(_egl_surface_height, texheight),
- 1 << 16);
+ xdiv(_egl_surface_height, texheight),
+ 1 << 16);
// Note the extra half texel to position the mouse in
// the middle of the x,y square:
@@ -801,14 +796,11 @@ void OSystem_Android::updateScreen() {
CHECK_GL_ERROR();
- if (!eglSwapBuffers(_egl_display, _egl_surface)) {
- EGLint error = eglGetError();
- warning("eglSwapBuffers exited with error 0x%x", error);
- // Some errors mean we need to reinit GL
- if (error == EGL_CONTEXT_LOST) {
- destroyScummVMSurface();
- setupScummVMSurface();
- }
+ JNIEnv* env = JNU_GetEnv();
+ if (!env->CallBooleanMethod(_back_ptr, MID_swapBuffers)) {
+ // Context lost -> need to reinit GL
+ destroyScummVMSurface();
+ setupScummVMSurface();
}
}
@@ -841,26 +833,18 @@ void OSystem_Android::fillScreen(uint32 col) {
void OSystem_Android::setFocusRectangle(const Common::Rect& rect) {
ENTER("setFocusRectangle(%d,%d,%d,%d)",
rect.left, rect.top, rect.right, rect.bottom);
-#if 0
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrthof(rect.left, rect.right, rect.top, rect.bottom, 0, 1);
- glMatrixMode(GL_MODELVIEW);
-
- _force_redraw = true;
-#endif
+ if (_enable_zoning) {
+ _focus_rect = rect;
+ _force_redraw = true;
+ }
}
void OSystem_Android::clearFocusRectangle() {
ENTER("clearFocusRectangle()");
-#if 0
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrthof(0, _egl_surface_width, _egl_surface_height, 0, -1, 1);
- glMatrixMode(GL_MODELVIEW);
-
- _force_redraw = true;
-#endif
+ if (_enable_zoning) {
+ _focus_rect = Common::Rect();
+ _force_redraw = true;
+ }
}
void OSystem_Android::showOverlay() {
@@ -1338,6 +1322,17 @@ void AndroidPluginProvider::addCustomDirectories(Common::FSList &dirs) const {
}
#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 },
@@ -1352,6 +1347,10 @@ const static JNINativeMethod gMethods[] = {
(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
diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk
index 0bc8fa265e..95e848e0d9 100644
--- a/backends/platform/android/android.mk
+++ b/backends/platform/android/android.mk
@@ -4,7 +4,6 @@ AAPT = aapt
DX = dx
APKBUILDER = apkbuilder
ADB = adb -e
-ANDROID_JAR = $(ANDROID_SDK)/platforms/android-1.6/android.jar
JAVAC ?= javac
JAVACFLAGS = -source 1.5 -target 1.5
@@ -12,6 +11,14 @@ JAVACFLAGS = -source 1.5 -target 1.5
#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
diff --git a/backends/platform/android/module.mk b/backends/platform/android/module.mk
index fdb0ed2ac4..b457b388b1 100644
--- a/backends/platform/android/module.mk
+++ b/backends/platform/android/module.mk
@@ -3,11 +3,10 @@ MODULE := backends/platform/android
MODULE_OBJS := \
android.o asset-archive.o video.o
-MODULE_DIRS += \
- backends/platform/android/
-
-# 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)))
JAVA_SRC = \
$(MODULE)/org/inodes/gus/scummvm/ScummVM.java \
@@ -39,14 +38,22 @@ PLUGIN_RESOURCES = \
#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)
- $(CXX) $(PLUGIN_LDFLAGS) -shared $(LDFLAGS) -Wl,-soname,$(@F) -Wl,--no-undefined -o $@ $(PRE_OBJS_FLAGS) $(OBJS) $(POST_OBJS_FLAGS) $(LIBS)
+ $(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_JAR)
- $(AAPT) package -m -J backends/platform/android -M $< -S $(srcdir)/dists/android/res -I $(ANDROID_JAR)
+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)
@@ -63,14 +70,6 @@ build.tmp/plugins/classes.dex: $(JAVA_PLUGIN_SRC:backends/platform/android/%.jav
@$(MKDIR) -p $(@D)
$(DX) --dex --output=$@ build.tmp/classes.plugin
-resources.ap_: $(srcdir)/dists/android/AndroidManifest.xml $(RESOURCES) $(ASSETS) $(ANDROID_JAR) $(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_JAR) -F $@
-
-build.tmp/%/resources.ap_: build.tmp/%/AndroidManifest.xml build.stage/%/res/values/strings.xml build.stage/%/res/drawable/scummvm.png $(ANDROID_JAR)
- $(AAPT) package -f -M $< -S build.stage/$*/res -I $(ANDROID_JAR) -F $@
-
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) \
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
index f4dca0e7e5..d39aa363ef 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVM.java
@@ -12,7 +12,10 @@ 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;
@@ -30,11 +33,11 @@ import java.util.concurrent.Semaphore;
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
+ 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;
+ boolean scummVMRunning = false;
private native void create(AssetManager am);
@@ -54,49 +57,49 @@ public class ScummVM implements SurfaceHolder.Callback {
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[] = {
+ // 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) {
+ };
+ 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,
+ 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) {
+ public void surfaceDestroyed(SurfaceHolder holder) {
pushEvent(new Event(Event.EVENT_SCREEN_CHANGED));
try {
surfaceLock.acquire();
@@ -104,10 +107,10 @@ public class ScummVM implements SurfaceHolder.Callback {
Log.e(this.toString(),
"Interrupted while waiting for surface lock", e);
}
- }
+ }
- // Called by ScummVM thread (from initBackend)
- private void createScummVMGLContext() {
+ // 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];
@@ -126,10 +129,11 @@ public class ScummVM implements SurfaceHolder.Callback {
eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
EGL10.EGL_NO_CONTEXT, null);
- }
+ }
- // Called by ScummVM thread
- protected void setupScummVMSurface() {
+ // Called by ScummVM thread
+ static private boolean _log_version = true;
+ protected void setupScummVMSurface() {
try {
surfaceLock.acquire();
} catch (InterruptedException e) {
@@ -140,10 +144,30 @@ public class ScummVM implements SurfaceHolder.Callback {
eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig,
nativeSurface, null);
egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
- }
- // Called by ScummVM thread
- protected void destroyScummVMSurface() {
+ 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);
@@ -152,16 +176,28 @@ public class ScummVM implements SurfaceHolder.Callback {
}
surfaceLock.release();
- }
+ }
- public void setSurface(SurfaceHolder holder) {
+ 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);
@@ -179,10 +215,10 @@ public class ScummVM implements SurfaceHolder.Callback {
protected void showVirtualKeyboard(boolean enable) {}
protected String[] getSysArchives() { return new String[0]; }
protected String[] getPluginDirectories() { return new String[0]; }
- protected void initBackend() throws AudioSetupException {
+ protected void initBackend() throws AudioSetupException {
createScummVMGLContext();
initAudio();
- }
+ }
private static class AudioThread extends Thread {
final private int buf_size;
@@ -239,7 +275,7 @@ public class ScummVM implements SurfaceHolder.Callback {
break;
} else if (ret != len) {
Log.w(LOG_TAG, String.format(
- "Short audio write. Wrote %dB, not %dB",
+ "Short audio write. Wrote %dB, not %dB",
ret, buf.length));
// Buffer is full, so yield cpu for a while
Thread.sleep(100);
diff --git a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
index fb3cd6348f..b37b2b8a52 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/ScummVMActivity.java
@@ -1,7 +1,7 @@
package org.inodes.gus.scummvm;
-import android.app.AlertDialog;
import android.app.Activity;
+import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.res.Configuration;
import android.media.AudioManager;
@@ -9,13 +9,14 @@ 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.inputmethod.InputMethodManager;
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;
@@ -31,8 +32,27 @@ public class ScummVMActivity extends Activity {
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
diff --git a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
index efa3e1d2ef..7280aac7d4 100644
--- a/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
+++ b/backends/platform/android/org/inodes/gus/scummvm/Unpacker.java
@@ -34,6 +34,7 @@ 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;
@@ -79,7 +80,6 @@ public class Unpacker extends Activity {
if (cn != null) {
final Intent origIntent = getIntent();
Intent intent = new Intent();
- intent.setPackage(origIntent.getPackage());
intent.setComponent(cn);
if (origIntent.getExtras() != null)
intent.putExtras(origIntent.getExtras());
@@ -294,7 +294,7 @@ public class Unpacker extends Activity {
Intent intent = new Intent(ScummVMApplication.ACTION_PLUGIN_QUERY);
List<ResolveInfo> plugins = getPackageManager()
.queryBroadcastReceivers(intent, 0);
- if (plugins.isEmpty()) {
+ if (PLUGINS_ENABLED && plugins.isEmpty()) {
// No plugins installed
AlertDialog.Builder alert = new AlertDialog.Builder(this)
.setTitle(R.string.no_plugins_title)
diff --git a/backends/platform/android/scummvm-android-themeengine.patch b/backends/platform/android/scummvm-android-themeengine.patch
deleted file mode 100644
index 1eafe7fb62..0000000000
--- a/backends/platform/android/scummvm-android-themeengine.patch
+++ /dev/null
@@ -1,135 +0,0 @@
-diff -r 884e66fd1b9c gui/ThemeEngine.cpp
---- a/gui/ThemeEngine.cpp Tue Apr 13 09:30:52 2010 +1000
-+++ b/gui/ThemeEngine.cpp Fri May 28 23:24:43 2010 +1000
-@@ -390,21 +390,19 @@
-
- // 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()) {
-+ Common::ArchiveMemberPtr member = SearchMan.getMember(_themeFile);
-+ if (member && member->getName().hasSuffix(".zip")) {
- #ifdef USE_ZLIB
-- Common::Archive *zipArchive = Common::makeZipArchive(node);
-+ Common::Archive *zipArchive = Common::makeZipArchive(member->createReadStream());
-
- if (!zipArchive) {
-- warning("Failed to open Zip archive '%s'.", node.getPath().c_str());
-+ warning("Failed to open Zip archive '%s'.", member->getDisplayName().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()) {
-- _themeArchive = new Common::FSDirectory(node);
- }
- }
-
-@@ -1436,6 +1434,30 @@
- return tok.empty();
- }
-
-+bool ThemeEngine::themeConfigUsable(const Common::ArchiveMember &member, Common::String &themeName) {
-+ Common::File stream;
-+ bool foundHeader = false;
-+
-+ if (member.getName().hasSuffix(".zip")) {
-+#ifdef USE_ZLIB
-+ Common::Archive *zipArchive = Common::makeZipArchive(member.createReadStream());
-+
-+ if (zipArchive && zipArchive->hasFile("THEMERC")) {
-+ stream.open("THEMERC", *zipArchive);
-+ }
-+
-+ delete zipArchive;
-+#endif
-+ }
-+
-+ 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;
-@@ -1493,10 +1515,6 @@
- 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) {
-@@ -1509,10 +1527,7 @@
- }
- #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 +1546,34 @@
- output.clear();
- }
-
-+void ThemeEngine::listUsableThemes(Common::Archive &archive, Common::List<ThemeDescriptor> &list) {
-+ ThemeDescriptor td;
-+
-+#ifdef USE_ZLIB
-+ 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();
-+#endif
-+}
-+
- void ThemeEngine::listUsableThemes(const Common::FSNode &node, Common::List<ThemeDescriptor> &list, int depth) {
- if (!node.exists() || !node.isReadable() || !node.isDirectory())
- return;
-diff -r 884e66fd1b9c gui/ThemeEngine.h
---- a/gui/ThemeEngine.h Tue Apr 13 09:30:52 2010 +1000
-+++ b/gui/ThemeEngine.h Fri May 28 23:24:43 2010 +1000
-@@ -560,11 +560,13 @@
- 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/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 a4cde02ba6..bcaaf8e936 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 7f03f4c310..eedf75c256 100644
--- a/backends/platform/ds/arm9/makefile
+++ b/backends/platform/ds/arm9/makefile
@@ -110,18 +110,15 @@ 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 = STATIC_PLUGIN
- DEFINES += -DENABLE_SCUMM=STATIC_PLUGIN
- MODULES += engines/scumm
-
USE_ARM_GFX_ASM = 1
BUILD=scummvm-A
endif
ifdef DS_BUILD_B
- DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_B
+ DEFINES = -DDS_BUILD_B
LOGO = logob.bmp
ENABLE_SKY = STATIC_PLUGIN
ENABLE_QUEEN = STATIC_PLUGIN
@@ -129,14 +126,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 = STATIC_PLUGIN
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 = STATIC_PLUGIN
ENABLE_CINE = STATIC_PLUGIN
@@ -145,42 +142,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 = STATIC_PLUGIN
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 = STATIC_PLUGIN
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 = STATIC_PLUGIN
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 = STATIC_PLUGIN
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 = STATIC_PLUGIN
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 = STATIC_PLUGIN
BUILD=scummvm-K
@@ -188,28 +185,26 @@ endif
#ifdef DS_BUILD_L
-# DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_L
+# DEFINES = -DDS_BUILD_L
# LOGO = logog.bmp
# ENABLE_DRASCULA = STATIC_PLUGIN
# 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 = STATIC_PLUGIN
# BUILD=scummvm-K
#endif
ARM7BIN := -7 $(CURDIR)/../../arm7/arm7.bin
-ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;"
CC = arm-eabi-gcc
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
@@ -248,9 +243,6 @@ endif
DEFINES += -DREDUCE_MEMORY_USAGE
-# Removed, as these are done in portdefs.h
-# -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE
-
LDFLAGS = -specs=ds_arm9.specs -mthumb-interwork -mno-fpu -Wl,-Map,map.txt -Wl,--gc-sections
ifdef WRAP_MALLOC
@@ -258,9 +250,11 @@ ifdef WRAP_MALLOC
DEFINES += -DWRAP_MALLOC
endif
+BACKEND := ds
+
INCLUDES= -I$(portdir)/$(BUILD) -I$(srcdir) -I$(srcdir)/engines \
-I$(portdir)/data -I$(portdir)/../commoninclude \
- -I$(portdir)/source -I$(portdir)/source/mad -I$(portdir)/source/libcartreset \
+ -I$(portdir)/source -I$(portdir)/source/mad \
-I$(libndsdir)/include -include $(srcdir)/common/scummsys.h
@@ -272,12 +266,7 @@ ifdef USE_DEBUGGER
LIBS += -ldsdebugger -ldswifi9
endif
-#-Lscumm -lscumm -Lbase -lbase -Lcommon -lcommon -Lgraphics -lgraphics -Lgui -lgui -Lsound -lsound
EXECUTABLE = scummvm.elf
-PLUGIN_PREFIX =
-PLUGIN_SUFFIX = .plg
-PLUGIN_EXTRA_DEPS = plugin.x plugin.syms scummvm.elf
-PLUGIN_LDFLAGS = -nostartfiles -Wl,-q,-Tplugin.x,--just-symbols,scummvm.elf,--retain-symbols-file,plugin.syms -L$(ronindir)/lib
MKDIR = mkdir -p
RM = rm -f
RM_REC = rm -rf
@@ -287,73 +276,68 @@ OBJCOPY = arm-eabi-objcopy
AS = arm-eabi-as
HAVE_GCC3 = true
-ifdef DYNAMIC_MODULES
-DEFINES += -DDYNAMIC_MODULES
-PRE_OBJS_FLAGS = -Wl,--whole-archive
-POST_OBJS_FLAGS = -Wl,--no-whole-archive
-endif
-
-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/portdefs.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
-
-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
+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
-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) $(LIBCARTRESET_OBJS) $(PORT_OBJS) $(COMPRESSOR_OBJS) $(FAT_OBJS)
+OBJS := $(DATA_OBJS) $(PORT_OBJS) $(FAT_OBJS)
@@ -361,7 +345,7 @@ MODULE_DIRS += .
ndsall:
@[ -d $(BUILD) ] || mkdir -p $(BUILD)
- make -C ./$(BUILD) -f ../makefile scummvm.nds
+ make -C ./$(BUILD) -f ../makefile scummvm.nds scummvm.ds.gba
include $(srcdir)/Makefile.common
@@ -372,25 +356,12 @@ clean:
$(RM) $(OBJS) $(EXECUTABLE)
rm -fr $(BUILD)
-plugin_dist :
- find . -name '*.plg' | while read p; do \
- sh-elf-strip -g -o "`basename \"$$p\" | tr '[:lower:]' '[:upper:]'`" "$$p"; \
- done
-
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
@@ -399,34 +370,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
@@ -434,12 +381,6 @@ endef
#---------------------------------------------------------------------------------
#---------------------------------------------------------------------------------
-%.o : %.pcx
-#---------------------------------------------------------------------------------
- @echo $(notdir $<)
- @$(bin2o)
-
-#---------------------------------------------------------------------------------
%.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@@ -458,30 +399,16 @@ 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 5a63e5f08f..95bfdfe40a 100644
--- a/backends/platform/ds/arm9/source/dsmain.cpp
+++ b/backends/platform/ds/arm9/source/dsmain.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$
*
*/
@@ -70,8 +73,6 @@
-//#define USE_LIBCARTRESET
-
#include <nds.h>
#include <nds/registers_alt.h>
#include <nds/arm9/exceptions.h>
@@ -80,8 +81,10 @@
//#include <ARM9/console.h> //basic print funcionality
#include <stdlib.h>
+#include <string.h>
+
+#include "NDS/scummvm_ipc.h"
#include "dsmain.h"
-#include "string.h"
#include "osystem_ds.h"
#include "icons_raw.h"
#include "fat/gba_nds_fat.h"
@@ -95,19 +98,19 @@
#ifdef USE_DEBUGGER
#include "user_debugger.h"
#endif
-#include "ramsave.h"
#include "blitters.h"
-#include "cartreset_nolibfat.h"
#include "keys.h"
#ifdef USE_PROFILER
#include "profiler/cyg-profile.h"
#endif
+#include "engine.h"
+
#include "backends/fs/ds/ds-fs.h"
#include "base/version.h"
-#include "engine.h"
+#include "common/util.h"
extern "C" void OurIntrMain(void);
-extern "C" u32 getExceptionAddress( u32 opcodeAddress, u32 thumbState);
+extern "C" u32 getExceptionAddress(u32 opcodeAddress, u32 thumbState);
extern const char __itcm_start[];
static const char *registerNames[] =
@@ -116,22 +119,20 @@ static const char *registerNames[] =
#ifdef WRAP_MALLOC
-extern "C" void* __real_malloc(size_t size);
+extern "C" void *__real_malloc(size_t size);
-int total = 0;
+static int s_total_malloc = 0;
-void* operator new (size_t size)
-{
+void *operator new (size_t size) {
register unsigned int reg asm("lr");
volatile unsigned int poo = reg;
- void* res = __real_malloc(size);
- total += size;
+ void *res = __real_malloc(size);
+ s_total_malloc += size;
- if (!res)
- {
+ if (!res) {
// *((u8 *) NULL) = 0;
- consolePrintf("Failed alloc (new) %d (%d)\n", size, total);
+ consolePrintf("Failed alloc (new) %d (%d)\n", size, s_total_malloc);
return NULL;
}
@@ -139,7 +140,7 @@ void* operator new (size_t size)
}
-extern "C" void* __wrap_malloc(size_t size) {
+extern "C" void *__wrap_malloc(size_t size) {
/* u32 addr;
asm("mov %0, lr"
@@ -151,23 +152,22 @@ extern "C" void* __wrap_malloc(size_t size) {
volatile unsigned int poo = reg;
- if (size == 0)
- {
+ if (size == 0) {
static int zeroSize = 0;
consolePrintf("0 size malloc (%d)", zeroSize++);
}
- void* res = __real_malloc(size);
+ void *res = __real_malloc(size);
if (res) {
if (size > 50 * 1024) {
consolePrintf("Allocated %d (%x)\n", size, poo);
}
- total += size;
+ s_total_malloc += size;
return res;
} else {
// *((u8 *) NULL) = 0;
- consolePrintf("Failed alloc %d (%d)\n", size, total);
+ consolePrintf("Failed alloc %d (%d)\n", size, s_total_malloc);
return NULL;
}
}
@@ -193,112 +193,109 @@ enum MouseMode {
#define SCUMM_GAME_HEIGHT 142
#define SCUMM_GAME_WIDTH 227
-int textureID;
-u16* texture;
-
-int frameCount;
-int currentTimeMillis;
+static int frameCount;
+static int currentTimeMillis;
// Timer Callback
-int callbackInterval;
-int callbackTimer;
-OSystem_DS::TimerProc callback;
+static int callbackInterval;
+static int callbackTimer;
+static OSystem_DS::TimerProc callback;
// Scaled
-bool scaledMode;
-int scX;
-int scY;
+static bool scaledMode;
+static int scX;
+static int scY;
-int subScX;
-int subScY;
-int subScTargetX;
-int subScTargetY;
-int subScreenWidth = SCUMM_GAME_WIDTH;
-int subScreenHeight = SCUMM_GAME_HEIGHT;
-int subScreenScale = 256;
+static int subScX;
+static int subScY;
+static int subScTargetX;
+static int subScTargetY;
+static int subScreenWidth = SCUMM_GAME_WIDTH;
+static int subScreenHeight = SCUMM_GAME_HEIGHT;
+static int subScreenScale = 256;
// Sound
-int bufferSize;
-s16* soundBuffer;
-int bufferFrame;
-int bufferRate;
-int bufferSamples;
-bool soundHiPart;
-int soundFrequency;
+static int bufferSize;
+static s16 *soundBuffer;
+static int bufferFrame;
+static int bufferRate;
+static int bufferSamples;
+static bool soundHiPart;
+static int soundFrequency;
// Events
-int lastEventFrame;
-bool indyFightState;
-bool indyFightRight;
+static int lastEventFrame;
+static bool indyFightState;
+static bool indyFightRight;
-OSystem_DS::SoundProc soundCallback;
-void* soundParam;
-int lastCallbackFrame;
-bool bufferFirstHalf;
-bool bufferSecondHalf;
+static OSystem_DS::SoundProc soundCallback;
+static int lastCallbackFrame;
+static bool bufferFirstHalf;
+static bool bufferSecondHalf;
// Saved buffers
-bool highBuffer;
-bool displayModeIs8Bit = false;
+static bool highBuffer;
+static bool displayModeIs8Bit = false;
// Game id
-u8 gameID;
+static u8 gameID;
-bool snapToBorder = false;
-bool consoleEnable = false;
-bool gameScreenSwap = false;
+static bool snapToBorder = false;
+static bool consoleEnable = false;
+static bool gameScreenSwap = false;
bool isCpuScalerEnabled();
//#define HEAVY_LOGGING
-MouseMode mouseMode = MOUSE_LEFT;
+static MouseMode mouseMode = MOUSE_LEFT;
-int storedMouseX = 0;
-int storedMouseY = 0;
+static int storedMouseX = 0;
+static int storedMouseY = 0;
// Sprites
-SpriteEntry sprites[128];
-SpriteEntry spritesMain[128];
-int tweak;
+static SpriteEntry sprites[128];
+static SpriteEntry spritesMain[128];
+static int tweak;
// Shake
-int shakePos = 0;
+static int s_shakePos = 0;
// Keyboard
-bool keyboardEnable = false;
-bool leftHandedMode = false;
-bool keyboardIcon = false;
+static bool keyboardEnable = false;
+static bool leftHandedMode = false;
+static bool keyboardIcon = false;
// Touch
-int touchScX, touchScY, touchX, touchY;
-int mouseHotspotX, mouseHotspotY;
-bool cursorEnable = false;
-bool mouseCursorVisible = true;
-bool rightButtonDown = false;
-bool touchPadStyle = false;
-int touchPadSensitivity = 8;
-bool tapScreenClicks = true;
-
-int tapCount = 0;
-int tapTimeout = 0;
-int tapComplete = 0;
+static int touchScX, touchScY, touchX, touchY;
+static int mouseHotspotX, mouseHotspotY;
+static bool cursorEnable = false;
+static bool mouseCursorVisible = true;
+static bool leftButtonDown = false;
+static bool rightButtonDown = false;
+static bool touchPadStyle = false;
+static int touchPadSensitivity = 8;
+static bool tapScreenClicks = true;
+
+static int tapCount = 0;
+static int tapTimeout = 0;
+static int tapComplete = 0;
// Dragging
-int dragStartX, dragStartY;
-bool dragging = false;
-int dragScX, dragScY;
+static int dragStartX, dragStartY;
+static bool dragging = false;
+static int dragScX, dragScY;
// Interface styles
-char gameName[32];
+static char gameName[32];
// 8-bit surface size
-int gameWidth = 320;
-int gameHeight = 200;
+static int gameWidth = 320;
+static int gameHeight = 200;
// Scale
-bool twoHundredPercentFixedScale = false;
-bool cpuScalerEnable = false;
+static bool twoHundredPercentFixedScale = false;
+static bool cpuScalerEnable = false;
// 100 256
// 150 192
@@ -309,14 +306,14 @@ bool cpuScalerEnable = false;
#ifdef USE_PROFILER
-int hBlankCount = 0;
+static int hBlankCount = 0;
#endif
-u8* scalerBackBuffer = NULL;
+static u8 *scalerBackBuffer = NULL;
#define NUM_SUPPORTED_GAMES 21
-gameListType gameList[NUM_SUPPORTED_GAMES] = {
+static const gameListType gameList[NUM_SUPPORTED_GAMES] = {
// Unknown game - use normal SCUMM controls
{"unknown", CONT_SCUMM_ORIGINAL},
@@ -345,31 +342,29 @@ gameListType gameList[NUM_SUPPORTED_GAMES] = {
{"parallaction", CONT_NIPPON},
};
-gameListType* currentGame = NULL;
+static const gameListType *s_currentGame = NULL;
// Stylus
-#define ABS(x) ((x)>0?(x):-(x))
-
-bool penDown = FALSE;
-bool penHeld = FALSE;
-bool penReleased = FALSE;
-bool penDownLastFrame = FALSE;
-s32 penX = 0, penY = 0;
-s32 penDownX = 0, penDownY = 0;
-int keysDownSaved = 0;
-int keysReleasedSaved = 0;
-int keysChangedSaved = 0;
+static bool penDown = FALSE;
+static bool penHeld = FALSE;
+static bool penReleased = FALSE;
+static bool penDownLastFrame = FALSE;
+static s32 penX = 0, penY = 0;
+static s32 penDownX = 0, penDownY = 0;
+static int keysDownSaved = 0;
+static int keysReleasedSaved = 0;
+static int keysChangedSaved = 0;
-bool penDownSaved = FALSE;
-bool penReleasedSaved = FALSE;
-int penDownFrames = 0;
-int touchXOffset = 0;
-int touchYOffset = 0;
+static bool penDownSaved = FALSE;
+static bool penReleasedSaved = FALSE;
+static int penDownFrames = 0;
+static int touchXOffset = 0;
+static int touchYOffset = 0;
-int triggeredIcon = 0;
-int triggeredIconTimeout = 0;
+static int triggeredIcon = 0;
+static int triggeredIconTimeout = 0;
-u16 savedPalEntry255 = RGB15(31, 31, 31);
+static u16 savedPalEntry255 = RGB15(31, 31, 31);
extern "C" int scummvm_main(int argc, char *argv[]);
@@ -382,8 +377,11 @@ void setIcon(int num, int x, int y, int imageNum, int flags, bool enable);
void setIconMain(int num, int x, int y, int imageNum, int flags, bool enable);
void uploadSpriteGfx();
-TransferSound soundControl;
+static TransferSound soundControl;
+static bool isScrollingWithDPad() {
+ return (getKeysHeld() & (KEY_L | KEY_R)) != 0;
+}
bool isCpuScalerEnabled() {
return cpuScalerEnable || !displayModeIs8Bit;
@@ -430,12 +428,12 @@ void setTopScreenZoom(int percentage) {
// return (ConfMan.hasKey("cpu_scaler", "ds") && ConfMan.getBool("cpu_scaler", "ds"));
controlType getControlType() {
- return currentGame->control;
+ return s_currentGame->control;
}
//plays an 8 bit mono sample at 11025Hz
-void playSound(const void* data, u32 length, bool loop, bool adpcm, int rate) {
+void playSound(const void *data, u32 length, bool loop, bool adpcm, int rate) {
if (!IPC->soundData) {
soundControl.count = 0;
@@ -551,21 +549,8 @@ int getSoundFrequency() {
return soundFrequency;
}
-void setControls(char* gameName) {
-
- for (int r = 0; r < NUM_SUPPORTED_GAMES; r++) {
- if (!stricmp(gameName, gameList[r].gameId)) {
- currentGame = &gameList[r];
- consolePrintf("Current game set to: %s\n", gameName);
- return;
- }
- }
-
- consolePrintf("Failed to set current game to: %s\n", gameName);
-}
-
void exitGame() {
- currentGame = NULL;
+ s_currentGame = NULL;
}
void initGame() {
@@ -580,17 +565,17 @@ void initGame() {
setOptions();
//strcpy(gameName, ConfMan.getActiveDomain().c_str());
- if (currentGame == NULL) {
+ if (s_currentGame == NULL) {
strcpy(gameName, ConfMan.get("gameid").c_str());
// consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]);
- currentGame = &gameList[0]; // Default game
+ s_currentGame = &gameList[0]; // Default game
for (int r = 0; r < NUM_SUPPORTED_GAMES; r++) {
if (!stricmp(gameName, gameList[r].gameId)) {
- currentGame = &gameList[r];
- // consolePrintf("Game list num: %d\n", currentGame);
+ s_currentGame = &gameList[r];
+ // consolePrintf("Game list num: %d\n", s_currentGame);
}
}
}
@@ -785,7 +770,7 @@ void checkSleepMode() {
}
void setShowCursor(bool enable) {
- if ((currentGame) && (currentGame->control == CONT_SCUMM_SAMNMAX)) {
+ if ((s_currentGame) && (s_currentGame->control == CONT_SCUMM_SAMNMAX)) {
if (cursorEnable) {
sprites[1].attribute[0] = ATTR0_BMP | 150;
} else {
@@ -801,7 +786,7 @@ void setMouseCursorVisible(bool enable) {
mouseCursorVisible = enable;
}
-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) {
int off;
@@ -833,7 +818,7 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX,
}
}
- if (currentGame->control != CONT_SCUMM_SAMNMAX)
+ if (s_currentGame->control != CONT_SCUMM_SAMNMAX)
return;
uint16 border = RGB15(24,24,24) | 0x8000;
@@ -982,7 +967,7 @@ void displayMode16BitFlipBuffer() {
consolePrintf("Flip %s...", displayModeIs8Bit ? "8bpp" : "16bpp");
#endif
if (!displayModeIs8Bit) {
- u16* back = get16BitBackBuffer();
+ u16 *back = get16BitBackBuffer();
// highBuffer = !highBuffer;
// BG3_CR = BG_BMP16_512x256 | BG_BMP_RAM(highBuffer? 1: 0);
@@ -1001,8 +986,8 @@ void displayMode16BitFlipBuffer() {
TIMER1_CR = TIMER_ENABLE | TIMER_DIV_1024;
u16 t0 = TIMER1_DATA;
#endif
- const u8* back = (const u8*)get8BitBackBuffer();
- u16* base = BG_GFX + 0x10000;
+ const u8 *back = (const u8*)get8BitBackBuffer();
+ u16 *base = BG_GFX + 0x10000;
Rescale_320x256xPAL8_To_256x256x1555(
base,
back,
@@ -1031,17 +1016,18 @@ void displayMode16BitFlipBuffer() {
}
void setShakePos(int shakePos) {
- shakePos = shakePos;
+ s_shakePos = shakePos;
}
-u16* get16BitBackBuffer() {
+u16 *get16BitBackBuffer() {
return BG_GFX + 0x20000;
}
s32 get8BitBackBufferStride() {
- // When the CPU scaler is enabled, the back buffer is in system RAM and is 320 pixels wide
- // When the CPU scaler is disabled, the back buffer is in video memory and therefore must have a 512 pixel stride
+ // When the CPU scaler is enabled, the back buffer is in system RAM and is
+ // 320 pixels wide. When the CPU scaler is disabled, the back buffer is in
+ // video memory and therefore must have a 512 pixel stride.
if (isCpuScalerEnabled()){
return 320;
@@ -1050,11 +1036,11 @@ s32 get8BitBackBufferStride() {
}
}
-u16* getScalerBuffer() {
+u16 *getScalerBuffer() {
return (u16 *) scalerBackBuffer;
}
-u16* get8BitBackBuffer() {
+u16 *get8BitBackBuffer() {
if (isCpuScalerEnabled())
return (u16 *) scalerBackBuffer;
else
@@ -1124,7 +1110,7 @@ void soundUpdate() {
void memoryReport() {
int r = 0;
- int* p;
+ int *p;
do {
p = (int *) malloc(r * 8192);
free(p);
@@ -1132,7 +1118,7 @@ void memoryReport() {
} while ((p) && (r < 512));
int t = -1;
- void* block[1024];
+ void *block[1024];
do {
t++;
block[t] = (int *) malloc(4096);
@@ -1147,7 +1133,7 @@ void memoryReport() {
void addIndyFightingKeys() {
- OSystem_DS* system = OSystem_DS::instance();
+ OSystem_DS *system = OSystem_DS::instance();
Common::Event event;
event.type = Common::EVENT_KEYDOWN;
@@ -1247,7 +1233,7 @@ void addIndyFightingKeys() {
void setKeyboardEnable(bool en) {
if (en == keyboardEnable) return;
keyboardEnable = en;
- u16* backupBank = (u16 *) 0x6040000;
+ u16 *backupBank = (u16 *) 0x6040000;
if (keyboardEnable) {
@@ -1283,7 +1269,7 @@ void setKeyboardEnable(bool en) {
if (displayModeIs8Bit) {
// Copy the sub screen VRAM from the top screen - they should always be
// the same.
- u16* buffer = get8BitBackBuffer();
+ u16 *buffer = get8BitBackBuffer();
s32 stride = get8BitBackBufferStride();
for (int y = 0; y < gameHeight; y++) {
@@ -1319,8 +1305,7 @@ bool getIsDisplayMode8Bit() {
return displayModeIs8Bit;
}
-void doScreenTapMode(OSystem_DS* system)
-{
+void doScreenTapMode(OSystem_DS *system) {
Common::Event event;
static bool left = false, right = false;
@@ -1353,7 +1338,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;
@@ -1386,21 +1371,17 @@ void doScreenTapMode(OSystem_DS* system)
system->addEvent(event);
}
-void doButtonSelectMode(OSystem_DS* system)
-{
+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);
//consolePrintf("x=%d y=%d \n", getPenX(), getPenY());
}
- static bool leftButtonDown = false;
- static bool rightButtonDown = false;
-
if (getPenReleased() && (leftButtonDown || rightButtonDown)) {
if (leftButtonDown) {
event.type = Common::EVENT_LBUTTONUP;
@@ -1417,7 +1398,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;
@@ -1459,7 +1440,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) {
@@ -1467,7 +1448,6 @@ void doButtonSelectMode(OSystem_DS* system)
}
if (rightButtonDown) {
- Common::Event event;
event.mouse = Common::Point(getPenX(), getPenY());
event.type = Common::EVENT_RBUTTONUP;
system->addEvent(event);
@@ -1476,14 +1456,13 @@ void doButtonSelectMode(OSystem_DS* system)
if (getKeysDown() & KEY_RIGHT) {
- if ((currentGame->control != CONT_SCUMM_SAMNMAX) && (currentGame->control != CONT_FUTURE_WARS) && (currentGame->control != CONT_GOBLINS)) {
+ if ((s_currentGame->control != CONT_SCUMM_SAMNMAX) && (s_currentGame->control != CONT_FUTURE_WARS) && (s_currentGame->control != CONT_GOBLINS)) {
mouseMode = MOUSE_RIGHT;
} else {
// If we're playing sam and max, click and release the right mouse
// button to change verb
- Common::Event event;
- if (currentGame->control == CONT_FUTURE_WARS) {
+ if (s_currentGame->control == CONT_FUTURE_WARS) {
event.mouse = Common::Point(320 - 128, 200 - 128);
event.type = Common::EVENT_MOUSEMOVE;
system->addEvent(event);
@@ -1515,7 +1494,7 @@ void addEventsToQueue() {
#ifdef HEAVY_LOGGING
consolePrintf("addEventsToQueue\n");
#endif
- OSystem_DS* system = OSystem_DS::instance();
+ OSystem_DS *system = OSystem_DS::instance();
Common::Event event;
#ifdef USE_PROFILER
@@ -1557,8 +1536,8 @@ void addEventsToQueue() {
if (!indyFightState) {
- if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) && (getKeysDown() & KEY_B)) {
- if (currentGame->control == CONT_AGI) {
+ if (!isScrollingWithDPad() && (getKeysDown() & KEY_B)) {
+ if (s_currentGame->control == CONT_AGI) {
event.kbd.keycode = Common::KEYCODE_RETURN;
event.kbd.ascii = 13;
event.kbd.flags = 0;
@@ -1596,8 +1575,7 @@ void addEventsToQueue() {
bool release = getKeysReleased() & (KEY_LEFT | KEY_RIGHT | KEY_UP | KEY_DOWN);
bool shoulders = getKeysHeld() & (KEY_L | KEY_R);
- if ( (down && (!shoulders)) || release)
- {
+ if ( (down && (!shoulders)) || release) {
if (getKeysChanged() & KEY_LEFT) {
event.kbd.keycode = Common::KEYCODE_LEFT;
@@ -1630,7 +1608,7 @@ void addEventsToQueue() {
}
- if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState()) && (!getKeyboardEnable())) {
+ if (!isScrollingWithDPad() && !getIndyFightState() && !getKeyboardEnable()) {
if ((getKeysDown() & KEY_A) && (!indyFightState)) {
gameScreenSwap = !gameScreenSwap;
@@ -1669,14 +1647,12 @@ void addEventsToQueue() {
}
}
- if (!getIndyFightState() && !((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (getKeysDown() & KEY_X)) {
+ if (!getIndyFightState() && !isScrollingWithDPad() && (getKeysDown() & KEY_X)) {
setKeyboardEnable(!keyboardEnable);
}
updateStatus();
- Common::Event event;
-
if ((tapScreenClicks) && (getIsDisplayMode8Bit())) {
if ((!keyboardEnable) || (!isInsideKeyboard(penDownX, penDownY))) {
@@ -1693,13 +1669,10 @@ void addEventsToQueue() {
if (!keyboardEnable) {
-
- if (((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) || (indyFightState)) && (displayModeIs8Bit)) {
+ if ((isScrollingWithDPad() || (indyFightState)) && (displayModeIs8Bit)) {
// Controls specific to the control method
-
-
- if (currentGame->control == CONT_SKY) {
+ if (s_currentGame->control == CONT_SKY) {
// Extra controls for Beneath a Steel Sky
if ((getKeysDown() & KEY_DOWN)) {
penY = 0;
@@ -1707,9 +1680,8 @@ void addEventsToQueue() {
}
}
- if (currentGame->control == CONT_AGI) {
+ if (s_currentGame->control == CONT_AGI) {
// Extra controls for Leisure Suit Larry and KQ4
-
if ((getKeysHeld() & KEY_UP) && (getKeysHeld() & KEY_START)
/*&& (!strcmp(gameName, "LLLLL"))*/) {
consolePrintf("Cheat key!\n");
@@ -1722,16 +1694,11 @@ void addEventsToQueue() {
event.type = Common::EVENT_KEYUP;
system->addEvent(event);
}
-
}
-
-
- if (currentGame->control == CONT_SIMON) {
+ if (s_currentGame->control == CONT_SIMON) {
// Extra controls for Simon the Sorcerer
if ((getKeysDown() & KEY_DOWN)) {
- Common::Event event;
-
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = Common::KEYCODE_F10; // F10 or # - show hotspots
event.kbd.ascii = Common::ASCII_F10;
@@ -1744,13 +1711,9 @@ void addEventsToQueue() {
}
}
-
-
- if (currentGame->control == CONT_SCUMM_ORIGINAL) {
+ if (s_currentGame->control == CONT_SCUMM_ORIGINAL) {
// Extra controls for Scumm v1-5 games
if ((getKeysDown() & KEY_DOWN)) {
- Common::Event event;
-
event.type = Common::EVENT_KEYDOWN;
event.kbd.keycode = Common::KEYCODE_PERIOD; // Full stop - skips current dialogue line
event.kbd.ascii = '.';
@@ -1806,14 +1769,14 @@ void addEventsToQueue() {
if ((getKeysChanged() & KEY_START)) {
event.kbd.flags = 0;
event.type = getKeyEvent(KEY_START);
- if (currentGame->control == CONT_FUTURE_WARS) {
+ if (s_currentGame->control == CONT_FUTURE_WARS) {
event.kbd.keycode = Common::KEYCODE_F10;
event.kbd.ascii = Common::ASCII_F10;
- } else if (currentGame->control == CONT_GOBLINS) {
+ } else if (s_currentGame->control == CONT_GOBLINS) {
event.kbd.keycode = Common::KEYCODE_F1;
event.kbd.ascii = Common::ASCII_F1;
// consolePrintf("!!!!!F1!!!!!");
- } else if (currentGame->control == CONT_AGI) {
+ } else if (s_currentGame->control == CONT_AGI) {
event.kbd.keycode = Common::KEYCODE_ESCAPE;
event.kbd.ascii = 27;
} else {
@@ -1830,9 +1793,7 @@ void addEventsToQueue() {
}
consumeKeys();
-
consumePenEvents();
-
}
}
@@ -1862,23 +1823,19 @@ void updateStatus() {
if (displayModeIs8Bit) {
if (!tapScreenClicks) {
switch (mouseMode) {
- case MOUSE_LEFT: {
- offs = 1;
- break;
- }
- case MOUSE_RIGHT: {
- offs = 2;
- break;
- }
- case MOUSE_HOVER: {
- offs = 0;
- break;
- }
- default: {
- // Nothing!
- offs = 0;
- break;
- }
+ case MOUSE_LEFT:
+ offs = 1;
+ break;
+ case MOUSE_RIGHT:
+ offs = 2;
+ break;
+ case MOUSE_HOVER:
+ offs = 0;
+ break;
+ default:
+ // Nothing!
+ offs = 0;
+ break;
}
setIcon(0, 208, 150, offs, 0, true);
@@ -1962,15 +1919,12 @@ void setMainScreenScale(int x, int y) {
SUB_BG3_YDX = 0;
SUB_BG3_YDY = y;
} else*/ {
- if (isCpuScalerEnabled() && (x==320))
- {
+ if (isCpuScalerEnabled() && (x==320)) {
BG3_XDX = 256;
BG3_XDY = 0;
BG3_YDX = 0;
BG3_YDY = y;
- }
- else
- {
+ } else {
BG3_XDX = x;
BG3_XDY = 0;
BG3_YDX = 0;
@@ -2057,11 +2011,9 @@ void VBlankHandler(void) {
soundUpdate();
-
-
- if ((!gameScreenSwap) && (!(getKeysHeld() & KEY_L) && !(getKeysHeld() & KEY_R))) {
- if (currentGame) {
- if (currentGame->control != CONT_SCUMM_SAMNMAX) {
+ if ((!gameScreenSwap) && !isScrollingWithDPad()) {
+ if (s_currentGame) {
+ if (s_currentGame->control != CONT_SCUMM_SAMNMAX) {
if (getPenHeld() && (getPenY() < SCUMM_GAME_HEIGHT)) {
setTopScreenTarget(getPenX(), getPenY());
}
@@ -2101,7 +2053,7 @@ void VBlankHandler(void) {
callbackTimer -= FRAME_TIME;
}
- if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) {
+ if (isScrollingWithDPad()) {
if ((!dragging) && (getPenHeld()) && (penDownFrames > 5)) {
dragging = true;
@@ -2144,7 +2096,7 @@ void VBlankHandler(void) {
SUB_BG3_CX = subScX + 64;
}
- SUB_BG3_CY = subScY + (shakePos << 8);*/
+ SUB_BG3_CY = subScY + (s_shakePos << 8);*/
/*SUB_BG3_XDX = (int) (subScreenWidth / 256.0f * 256);
SUB_BG3_XDY = 0;
@@ -2155,7 +2107,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;
@@ -2232,7 +2184,7 @@ void VBlankHandler(void) {
if (displayModeIs8Bit) {
- if ((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) {
+ if (isScrollingWithDPad()) {
int offsX = 0, offsY = 0;
@@ -2284,7 +2236,7 @@ void VBlankHandler(void) {
setZoomedScreenScale(subScreenWidth, ((subScreenHeight * (256 << 8)) / 192) >> 8);
- setMainScreenScroll(scX << 8, (scY << 8) + (shakePos << 8));
+ setMainScreenScroll(scX << 8, (scY << 8) + (s_shakePos << 8));
setMainScreenScale(256, 256); // 1:1 scale
} else {
@@ -2300,7 +2252,7 @@ void VBlankHandler(void) {
setZoomedScreenScroll(subScX, subScY, (subScreenWidth != 256) && (subScreenWidth != 128));
setZoomedScreenScale(subScreenWidth, ((subScreenHeight * (256 << 8)) / 192) >> 8);
- setMainScreenScroll(64, (scY << 8) + (shakePos << 8));
+ setMainScreenScroll(64, (scY << 8) + (s_shakePos << 8));
setMainScreenScale(320, 256); // 1:1 scale
}
@@ -2388,7 +2340,7 @@ void uploadSpriteGfx() {
vramSetBankE(VRAM_E_MAIN_SPRITE);
// Convert texture from 24bit 888 to 16bit 1555, remembering to set top bit!
- u8* srcTex = (u8 *) ::icons_raw;
+ const u8 *srcTex = (const u8 *) ::icons_raw;
for (int r = 32 * 256 ; r >= 0; r--) {
SPRITE_GFX_SUB[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10);
SPRITE_GFX[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10);
@@ -2634,9 +2586,6 @@ void penUpdate() {
}
}
- else
- {
- }
} else {
penDown = true;
@@ -2822,31 +2771,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;
@@ -2856,20 +2780,18 @@ bool getIndyFightState() {
return indyFightState;
}
-gameListType* getCurrentGame() {
- return currentGame;
-}
-
///////////////////
// Fast Ram
///////////////////
#define FAST_RAM_SIZE (24000)
-u8* fastRamPointer;
+#define ITCM_DATA __attribute__((section(".itcm")))
+
+u8 *fastRamPointer;
u8 fastRamData[FAST_RAM_SIZE] ITCM_DATA;
-void* fastRamAlloc(int size) {
- void* result = (void *) fastRamPointer;
+void *fastRamAlloc(int size) {
+ void *result = (void *) fastRamPointer;
fastRamPointer += size;
if(fastRamPointer > fastRamData + FAST_RAM_SIZE) {
consolePrintf("FastRam (ITCM) allocation failed!\n");
@@ -2926,68 +2848,13 @@ void initDebugger() {
// Ensure the function is processed with C linkage
-extern "C" void debug_print_stub(char* string);
+extern "C" void debug_print_stub(char *string);
void debug_print_stub(char *string) {
consolePrintf(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.
@@ -3002,12 +2869,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
+ }
}
}
@@ -3028,7 +2893,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) ||
@@ -3051,16 +2916,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] );
}
@@ -3286,7 +3154,7 @@ int main(void) {
*/
// Create a file system node to force search for a zip file in GBA rom space
- DSFileSystemNode* node = new DSFileSystemNode();
+ DSFileSystemNode *node = new DSFileSystemNode();
if (!node->getZip() || (!node->getZip()->isReady())) {
// If not found, init CF/SD driver
initGBAMP(mode);
@@ -3311,12 +3179,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());
@@ -3344,6 +3206,11 @@ int main(void) {
const char *argv[] = {"/scummvmds", "--config=scummvmj.ini"};
#elif defined(DS_BUILD_K)
const char *argv[] = {"/scummvmds", "--config=scummvmk.ini"};
+#else
+ // Use the default 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).
+ const char *argv[] = {"/scummvmds"};
#endif
@@ -3356,7 +3223,8 @@ int main(void) {
return 0;
}
-}
+} // End of namespace DS
+
int main() {
DS::main();
@@ -3377,7 +3245,6 @@ extern "C" void consolePrintf(char * format, ...) __attribute__ ((no_instrument_
extern "C" void consolePrintf(const char * format, ...) {
- char buffer[256];
va_list args;
va_start(args, format);
viprintf(format, args);
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/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/fat/io_nmmc.c b/backends/platform/ds/arm9/source/fat/io_nmmc.c
index 261096a27b..6c996f5de1 100644
--- a/backends/platform/ds/arm9/source/fat/io_nmmc.c
+++ b/backends/platform/ds/arm9/source/fat/io_nmmc.c
@@ -170,7 +170,7 @@ bool NMMC_IsInserted(void) {
Neo_EnableMMC( true ); // Open SPI port to MMC card
Neo_SendMMCCommand(MMC_SEND_CSD, 0);
- if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured
+ if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occurred
Neo_EnableMMC( false );
return false;
}
@@ -227,14 +227,14 @@ bool NMMC_StartUp(void) {
// Set block length
Neo_SendMMCCommand(MMC_SET_BLOCKLEN, BYTE_PER_READ );
- if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured
+ if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occurred
Neo_EnableMMC( false );
return false;
}
// Check if we can use a higher SPI frequency
Neo_SendMMCCommand(MMC_SEND_CSD, 0);
- if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured
+ if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occurred
Neo_EnableMMC( false );
return false;
}
@@ -268,7 +268,7 @@ bool NMMC_WriteSectors (u32 sector, u8 numSecs, void* buffer)
Neo_EnableMMC( true ); // Open SPI port to MMC card
Neo_SendMMCCommand( 25, sector );
- if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured
+ if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occurred
Neo_EnableMMC( false );
return false;
}
@@ -318,7 +318,7 @@ bool NMMC_ReadSectors (u32 sector, u8 numSecs, void* buffer)
while (totalSecs--) {
Neo_SendMMCCommand(MMC_READ_BLOCK, sector );
- if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occured
+ if( Neo_CheckMMCResponse( 0x00, 0xFF ) == false ) { // Make sure no errors occurred
Neo_EnableMMC( false );
return false;
}
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/module.mk b/backends/platform/ds/module.mk
index 16630dc070..7298267db4 100644
--- a/backends/platform/ds/module.mk
+++ b/backends/platform/ds/module.mk
@@ -8,12 +8,9 @@ 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/portdefs.o \
- arm9/source/ramsave.o \
arm9/source/touchkeyboard.o \
arm9/source/zipreader.o \
arm9/source/dsoptions.o \
@@ -21,10 +18,6 @@ PORT_OBJS := \
arm9/source/wordcompletion.o \
arm9/source/interrupt.o
-ifdef USE_PROFILER
- PORT_OBJS += arm9/source/profiler/cyg-profile.o
-endif
-
DATA_OBJS := \
arm9/data/icons.o \
arm9/data/keyboard.o \
@@ -32,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 \
@@ -51,21 +44,64 @@ 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
+MODULE_OBJS := $(DATA_OBJS) $(PORT_OBJS) $(FAT_OBJS)
+
+
+#---------------------------------------------------------------------------------
+# canned command sequence for binary data
+#---------------------------------------------------------------------------------
+define bin2o
+ $(MKDIR) $(*D)
+ bin2s $< | $(AS) -mthumb -mthumb-interwork -o $(@)
+endef
+
+define bin2h
+ $(MKDIR) $(*D)
+ echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > $@
+ echo "extern const u8" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> $@
+ echo "extern const u32" `(echo $(<F) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> $@
+endef
+
+vpath %.raw $(srcdir)
+vpath %.pal $(srcdir)
+vpath %.bin $(srcdir)
+
+%.o: %.raw
+ $(bin2o)
+
+%_raw.h: %.raw
+ $(bin2h)
+
+%.o: %.pal
+ $(bin2o)
+
+%_raw.h: %.pal
+ $(bin2h)
+
+%.o: %.bin
+ $(bin2o)
-LIBCARTRESET_OBJS :=
- #arm9/source/libcartreset/cartreset.o
+%_raw.h: %.bin
+ $(bin2h)
-MODULE_OBJS :=
+# Mark files which require the *_raw.h files manually (for now, at least)
+$(MODULE)/arm9/source/dsmain.o: \
+ $(MODULE)/arm9/data/icons_raw.h \
+ $(MODULE)/arm9/data/keyboard_raw.h \
+ $(MODULE)/arm9/data/keyboard_pal_raw.h
+$(MODULE)/arm9/source/touchkeyboard.o: \
+ $(MODULE)/arm9/data/keyboard_raw.h \
+ $(MODULE)/arm9/data/keyboard_pal_raw.h \
+ $(MODULE)/arm9/data/8x8font_tga_raw.h
-# TODO: Should add more dirs to MODULE_DIRS so that "make distclean" can remove .deps dirs.
MODULE_DIRS += \
- backends/platform/ds/
+ backends/platform/ds/arm7/source/ \
+ backends/platform/ds/arm7/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
new file mode 100755
index 0000000000..cd5145b31d
--- /dev/null
+++ b/backends/platform/gp2xwiz/build/bundle-debug.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+echo Quick script to make building a distribution of the GP2X Wiz backend more consistent.
+
+cd ../../../..
+
+echo Building ScummVM for GP2X 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/build/scummvm-gdb.gpe b/backends/platform/gp2xwiz/build/scummvm-gdb.gpe
new file mode 100755
index 0000000000..64b6c8b974
--- /dev/null
+++ b/backends/platform/gp2xwiz/build/scummvm-gdb.gpe
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+# Export the location of any libs ScummVM depends on
+# (to avoid installing to the NAND and overwriting the broken ones there).
+export LD_LIBRARY_PATH=`pwd`/lib:$LD_LIBRARY_PATH
+
+# Run ScummVM via GDB (so make sure you have a terminal open or serial).
+# Oh, and GDB installed of course ;)
+gdb --args ./scummvm.wiz --fullscreen --gfx-mode=1x --config=$(pwd)/.scummvmrc
+
+# Sync the SD card to check that everything is written.
+sync
+
+# Return to the GPH menu screen
+cd /usr/gp2x
+exec /usr/gp2x/gp2xmenu
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 6abddd52f3..f6ad226d42 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 f457d51615..edf2f2a717 100644
--- a/backends/platform/gp2xwiz/module.mk
+++ b/backends/platform/gp2xwiz/module.mk
@@ -6,11 +6,10 @@ MODULE_OBJS := \
gp2xwiz-hw.o \
gp2xwiz-main.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 bf7ac0aca0..d2a8d210e4 100644
--- a/backends/platform/ps2/Makefile.ps2
+++ b/backends/platform/ps2/Makefile.ps2
@@ -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/module.mk b/backends/platform/ps2/module.mk
index 86b12cb668..bf95a5501d 100644
--- a/backends/platform/ps2/module.mk
+++ b/backends/platform/ps2/module.mk
@@ -18,8 +18,7 @@ MODULE_OBJS := \
ps2time.o \
ps2debug.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 7f8bb63b0a..617ef7c8cc 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,17 +123,13 @@ 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 -lpspaudiocodec \
-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 \
@@ -151,7 +146,11 @@ OBJS := powerman.o \
pspkeyboard.o \
audio.o \
thread.o \
- mp3.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
index bf1fb9ab41..e540733162 100644
--- a/backends/platform/psp/audio.cpp
+++ b/backends/platform/psp/audio.cpp
@@ -28,7 +28,6 @@
#include "common/scummsys.h"
#include "backends/platform/psp/audio.h"
-#include "backends/platform/psp/thread.h"
//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
@@ -85,43 +84,13 @@ bool PspAudio::open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, call
_init = true;
_paused = true; // start in paused mode
- createThread();
+ threadCreateAndStart("audioThread", PRIORITY_AUDIO_THREAD, STACK_AUDIO_THREAD); // start the consumer thread
return true;
}
-bool PspAudio::createThread() {
- DEBUG_ENTER_FUNC();
- int threadId = sceKernelCreateThread("audioThread", thread, PRIORITY_AUDIO_THREAD, STACK_AUDIO_THREAD, THREAD_ATTR_USER, 0);
-
- if (threadId < 0) { // error
- PSP_ERROR("failed to create audio thread. Error code %d\n", threadId);
- return false;
- }
-
- PspAudio *_this = this; // trick to get into context when the thread starts
-
- if (sceKernelStartThread(threadId, sizeof(uint32 *), &_this) < 0) {
- PSP_ERROR("failed to start thread %d\n", threadId);
- return false;
- }
-
- PSP_DEBUG_PRINT("created audio thread[%x]\n", threadId);
-
- return true;
-}
-
-// Static function to be called upon thread startup. Will call a non-static function
-int PspAudio::thread(SceSize, void *__this) {
- DEBUG_ENTER_FUNC();
- PspAudio *_this = *(PspAudio **)__this; // get our this for the context
-
- _this->audioThread();
- return 0;
-};
-
// The real thread function
-void PspAudio::audioThread() {
+void PspAudio::threadFunction() {
assert(_callback);
PSP_DEBUG_PRINT_FUNC("audio thread started\n");
@@ -129,15 +98,15 @@ void PspAudio::audioThread() {
if (_paused)
PSP_DEBUG_PRINT("audio thread paused\n");
while (_paused) { // delay until we stop pausing
- sceKernelDelayThread(100000); // 100ms
+ PspThread::delayMicros(100000); // 100ms
if (!_paused)
PSP_DEBUG_PRINT("audio thread unpaused\n");
}
- PSP_DEBUG_PRINT("remaining samples[%d]\n", remainingSamples);
+ 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
+ _callback(_userData, _buffers[_bufferToFill], _bufferSize); // ask mixer to fill in data
nextBuffer(_bufferToFill);
PSP_DEBUG_PRINT("playing buffer[%d].\n", _bufferToPlay);
@@ -151,7 +120,7 @@ void PspAudio::audioThread() {
PSP_DEBUG_PRINT("audio thread exiting. ****************************\n");
}
-// Much faster than using %
+// Much faster than using %, especially with conditional moves (MIPS)
inline void PspAudio::nextBuffer(int &bufferIdx) {
DEBUG_ENTER_FUNC();
bufferIdx++;
@@ -176,6 +145,6 @@ inline bool PspAudio::playBuffer() {
}
void PspAudio::close() {
- PSP_DEBUG_PRINT("close had been called ***************\n");
+ PSP_DEBUG_PRINT("close has been called ***************\n");
_init = false;
}
diff --git a/backends/platform/psp/audio.h b/backends/platform/psp/audio.h
index 603f8f6bfc..eeba598fed 100644
--- a/backends/platform/psp/audio.h
+++ b/backends/platform/psp/audio.h
@@ -26,13 +26,15 @@
#ifndef PSP_AUDIO_H
#define PSP_AUDIO_H
-class PspAudio {
+#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);
+ 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),
@@ -43,14 +45,12 @@ public:
~PspAudio() { close(); }
bool playBuffer();
void nextBuffer(int &bufferIdx);
- static int thread(SceSize, void *);
- void audioThread();
bool open(uint32 freq, uint32 numOfChannels, uint32 numOfSamples, callbackFunc callback, void *userData);
- bool createThread();
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
diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp
index c5a6250188..71b505ec7c 100644
--- a/backends/platform/psp/display_client.cpp
+++ b/backends/platform/psp/display_client.cpp
@@ -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);
diff --git a/backends/platform/psp/display_manager.cpp b/backends/platform/psp/display_manager.cpp
index c2f21e084b..5037543f12 100644
--- a/backends/platform/psp/display_manager.cpp
+++ b/backends/platform/psp/display_manager.cpp
@@ -34,7 +34,6 @@
#include "backends/platform/psp/default_display_client.h"
#include "backends/platform/psp/cursor.h"
#include "backends/platform/psp/pspkeyboard.h"
-#include "backends/platform/psp/thread.h"
#define USE_DISPLAY_CALLBACK // to use callback for finishing the render
#include "backends/platform/psp/display_manager.h"
@@ -65,37 +64,24 @@ const OSystem::GraphicsMode DisplayManager::_supportedModes[] = {
void MasterGuRenderer::setupCallbackThread() {
DEBUG_ENTER_FUNC();
- int thid = sceKernelCreateThread("displayCbThread", guCallbackThread, PRIORITY_DISPLAY_THREAD, STACK_DISPLAY_THREAD, 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
@@ -311,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",
@@ -361,6 +349,8 @@ void DisplayManager::renderAll() {
_keyboard->setClean();
_masterGuRenderer.guPostRender();
+
+ return true; // rendered successfully
}
inline bool DisplayManager::isTimeToUpdate() {
@@ -375,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..1f7320902c 100644
--- a/backends/platform/psp/display_manager.h
+++ b/backends/platform/psp/display_manager.h
@@ -26,10 +26,12 @@
#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/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 99170ce7fb..4652189ab4 100644
--- a/backends/platform/psp/module.mk
+++ b/backends/platform/psp/module.mk
@@ -15,10 +15,11 @@ MODULE_OBJS := powerman.o \
pspkeyboard.o \
audio.o \
thread.o \
- mp3.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
index 972c5a8ba8..e25891396b 100644
--- a/backends/platform/psp/mp3.cpp
+++ b/backends/platform/psp/mp3.cpp
@@ -85,13 +85,13 @@ bool Mp3PspStream::initDecoder() {
}
} else {
if (sceUtilityLoadAvModule(PSP_AV_MODULE_AVCODEC) < 0) {
- PSP_ERROR("failed to load AVCODEC module.\n");
+ PSP_ERROR("failed to load AVCODEC module. ME cannot start.\n");
_decoderFail = true;
return false;
}
}
- PSP_INFO_PRINT("Using PSP's ME for MP3\n"); // important to know this is happening
+ PSP_DEBUG_PRINT("Using PSP's ME for MP3\n"); // important to know this is happening
_decoderInit = true;
return true;
@@ -319,7 +319,7 @@ void Mp3PspStream::decodeMP3Data() {
// This function blocks. We'll want to put it in a thread
int ret = sceAudiocodecDecode(_codecParams, 0x1002);
if (ret < 0) {
- PSP_ERROR("failed to decode MP3 data in ME. sceAudiocodecDecode returned 0x%x\n", ret);
+ PSP_INFO_PRINT("failed to decode MP3 data in ME. sceAudiocodecDecode returned 0x%x\n", ret);
// handle error here
}
diff --git a/backends/platform/psp/mp3.h b/backends/platform/psp/mp3.h
index f8802f930c..029b3e498c 100644
--- a/backends/platform/psp/mp3.h
+++ b/backends/platform/psp/mp3.h
@@ -110,7 +110,7 @@ public:
bool endOfData() const { return _state == MP3_STATE_EOS; }
bool isStereo() const { return MAD_NCHANNELS(&_header) == 2; }
- int getRate() const { return _header.samplerate; }
+ int getRate() const { return _sampleRate; }
bool seek(const Timestamp &where);
Timestamp getLength() const { return _length; }
diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp
index 2043a4bef2..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,8 +49,6 @@
#include "backends/platform/psp/trace.h"
-#define USE_PSP_AUDIO
-
#define SAMPLES_PER_SEC 44100
static int timer_handler(int t) {
@@ -58,14 +57,6 @@ static int timer_handler(int t) {
return t;
}
-void OSystem_PSP::initSDL() {
-#ifdef USE_PSP_AUDIO
- SDL_Init(0);
-#else
- SDL_Init(SDL_INIT_AUDIO);
-#endif
-}
-
OSystem_PSP::~OSystem_PSP() {}
#define PSP_SCREEN_WIDTH 480
@@ -74,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
@@ -89,8 +83,6 @@ void OSystem_PSP::initBackend() {
_inputHandler.setKeyboard(&_keyboard);
_inputHandler.init();
- initSDL();
-
_savefile = new PSPSaveFileManager;
_timer = new DefaultTimerManager();
@@ -127,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);
}
@@ -146,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();
}
@@ -154,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);
@@ -172,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();
@@ -179,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?
@@ -186,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
@@ -224,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
@@ -231,6 +235,7 @@ void OSystem_PSP::hideOverlay() {
void OSystem_PSP::clearOverlay() {
DEBUG_ENTER_FUNC();
+ _pendingUpdate = false;
_overlay.clearBuffer();
}
@@ -241,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);
}
@@ -259,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);
@@ -268,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);
@@ -292,14 +303,28 @@ 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 _pspRtc.getMillis();
+ return PspRtc::instance().getMillis();
}
void OSystem_PSP::delayMillis(uint msecs) {
@@ -313,19 +338,19 @@ void OSystem_PSP::setTimerCallback(TimerProc callback, int interval) {
}
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) {
@@ -355,7 +380,6 @@ void OSystem_PSP::setupMixer(void) {
assert(!_mixer);
-#ifdef USE_PSP_AUDIO
if (!_audio.open(samplesPerSec, 2, samples, mixCallback, this)) {
PSP_ERROR("failed to open audio\n");
return;
@@ -365,46 +389,10 @@ void OSystem_PSP::setupMixer(void) {
assert(_mixer);
_mixer->setReady(true);
_audio.unpause();
-#else
- SDL_AudioSpec obtained;
- SDL_AudioSpec desired;
-
- memset(&desired, 0, sizeof(desired));
- desired.freq = samplesPerSec;
- desired.format = AUDIO_S16SYS;
- desired.channels = 2;
- desired.samples = samples;
- desired.callback = mixCallback;
- desired.userdata = this;
-
- 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);
- }
-#endif /* USE_PSP_AUDIO */
}
void OSystem_PSP::quit() {
-#ifdef USE_PSP_AUDIO
_audio.close();
-#else
- SDL_CloseAudio();
-#endif
- SDL_Quit();
sceKernelExitGame();
}
diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h
index a6c84ba39a..5721296c94 100644
--- a/backends/platform/psp/osys_psp.h
+++ b/backends/platform/psp/osys_psp.h
@@ -42,14 +42,14 @@
#include "backends/timer/psp/timer.h"
#include "backends/platform/psp/thread.h"
-#include <SDL.h>
-
class OSystem_PSP : public BaseBackend {
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;
@@ -60,12 +60,9 @@ private:
InputHandler _inputHandler;
PspAudio _audio;
PspTimer _pspTimer;
- PspRtc _pspRtc;
-
- void initSDL();
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();
@@ -85,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_main.cpp b/backends/platform/psp/psp_main.cpp
index e6940eba13..dba9a8fc2b 100644
--- a/backends/platform/psp/psp_main.cpp
+++ b/backends/platform/psp/psp_main.cpp
@@ -44,6 +44,7 @@
#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
@@ -110,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 */
@@ -168,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/psploader.cpp b/backends/platform/psp/psploader.cpp
index 68e51c1a50..464e20770c 100644
--- a/backends/platform/psp/psploader.cpp
+++ b/backends/platform/psp/psploader.cpp
@@ -37,24 +37,20 @@
#include "backends/platform/psp/psploader.h"
#include "backends/platform/psp/powerman.h"
-//#define __PSP_DEBUG_PLUGINS__
+//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */
+//#define __PSP_DEBUG_PRINT__
-#ifdef __PSP_DEBUG_PLUGINS__
-#define DBG(x,...) fprintf(stderr,x, ## __VA_ARGS__)
-#else
-#define DBG(x,...)
-#endif
-
-#define seterror(x,...) fprintf(stderr,x, ## __VA_ARGS__)
+#include "backends/platform/psp/trace.h"
extern char __plugin_hole_start; // Indicates start of hole in program file for shorts
extern char __plugin_hole_end; // Indicates end of hole in program file
-extern char _gp[]; // Value of gp register
+extern char _gp[]; // Value of gp register
DECLARE_SINGLETON(ShortSegmentManager) // For singleton
// Get rid of symbol table in memory
void DLObject::discard_symtab() {
+ DEBUG_ENTER_FUNC();
free(_symtab);
free(_strtab);
_symtab = NULL;
@@ -64,6 +60,7 @@ void DLObject::discard_symtab() {
// Unload all objects from memory
void DLObject::unload() {
+ DEBUG_ENTER_FUNC();
discard_symtab();
free(_segment);
_segment = NULL;
@@ -84,18 +81,19 @@ void DLObject::unload() {
*
*/
bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *relSegment) {
+ DEBUG_ENTER_FUNC();
Elf32_Rel *rel = NULL; // relocation entry
// Allocate memory for relocation table
if (!(rel = (Elf32_Rel *)malloc(size))) {
- seterror("Out of memory.");
+ PSP_ERROR("Out of memory.");
return false;
}
// Read in our relocation table
if (lseek(fd, offset, SEEK_SET) < 0 ||
read(fd, rel, size) != (ssize_t)size) {
- seterror("Relocation table load failed.");
+ PSP_ERROR("Relocation table load failed.");
free(rel);
return false;
}
@@ -103,7 +101,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *
// Treat each relocation entry. Loop over all of them
int cnt = size / sizeof(*rel);
- DBG("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment);
+ PSP_DEBUG_PRINT("Loaded relocation table. %d entries. base address=%p\n", cnt, relSegment);
bool seenHi16 = false; // For treating HI/LO16 commands
int firstHi16 = -1; // Mark the point of the first hi16 seen
@@ -127,7 +125,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *
// Get the target instruction in the code
unsigned int *target = (unsigned int *)((char *)relSegment + rel[i].r_offset);
- unsigned int origTarget = *target; // Save for debugging
+ PSP_DEBUG_DO(unsigned int origTarget = *target); // Save for debugging
// Act differently based on the type of relocation
switch (REL_TYPE(rel[i].r_info)) {
@@ -142,7 +140,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *
lastHiSymVal = sym->st_value;
hi16InShorts = (ShortsMan.inGeneralSegment((char *)sym->st_value)); // Fix for problem with switching btw segments
if (debugRelocs[0]++ < DEBUG_NUM) // Print only a set number
- DBG("R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x\n",
+ PSP_DEBUG_PRINT("R_MIPS_HI16: i=%d, offset=%x, ahl = %x, target = %x\n",
i, rel[i].r_offset, ahl, *target);
}
break;
@@ -150,7 +148,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *
case R_MIPS_LO16: // Absolute addressing. Needs a HI16 to come before it
if (sym->st_shndx < SHN_LOPROC) { // Only shift for plugin section. (ie. has a real section index)
if (!seenHi16) { // We MUST have seen HI16 first
- seterror("R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!\n", i);
+ PSP_ERROR("R_MIPS_LO16 w/o preceding R_MIPS_HI16 at relocation %d!\n", i);
free(rel);
return false;
}
@@ -195,10 +193,10 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *
*target |= relocation & 0xffff; // Take the lower 16 bits of the relocation
if (debugRelocs[1]++ < DEBUG_NUM)
- DBG("R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
+ PSP_DEBUG_PRINT("R_MIPS_LO16: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
if (lo16InShorts && debugRelocs[2]++ < DEBUG_NUM)
- DBG("R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
+ PSP_DEBUG_PRINT("R_MIPS_LO16s: i=%d, offset=%x, a=%x, ahl = %x, lastTarget = %x, origt = %x, target = %x\n",
i, rel[i].r_offset, a, ahl, *lastTarget, origTarget, *target);
}
break;
@@ -212,11 +210,11 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *
*target |= (relocation & 0x03ffffff);
if (debugRelocs[3]++ < DEBUG_NUM)
- DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
+ PSP_DEBUG_PRINT("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
} else {
if (debugRelocs[4]++ < DEBUG_NUM)
- DBG("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
+ PSP_DEBUG_PRINT("R_MIPS_26: i=%d, offset=%x, symbol=%d, stinfo=%x, a=%x, origTarget=%x, target=%x\n",
i, rel[i].r_offset, REL_INDEX(rel[i].r_info), sym->st_info, a, origTarget, *target);
}
break;
@@ -233,7 +231,7 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *
*target |= relocation & 0xffff;
if (debugRelocs[5]++ < DEBUG_NUM)
- DBG("R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x\n",
+ PSP_DEBUG_PRINT("R_MIPS_GPREL16: i=%d, a=%x, gpVal=%x, origTarget=%x, target=%x, offset=%x\n",
i, a, _gpVal, origTarget, *target, _shortsSegment->getOffset());
}
@@ -250,24 +248,25 @@ bool DLObject::relocate(int fd, unsigned long offset, unsigned long size, void *
*target = relocation;
if (debugRelocs[6]++ < DEBUG_NUM)
- DBG("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target);
+ PSP_DEBUG_PRINT("R_MIPS_32: i=%d, a=%x, origTarget=%x, target=%x\n", i, a, origTarget, *target);
}
break;
default:
- seterror("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i);
+ PSP_ERROR("Unknown relocation type %x at relocation %d.\n", REL_TYPE(rel[i].r_info), i);
free(rel);
return false;
}
}
- DBG("Done with relocation. extendedHi16=%d\n\n", extendedHi16);
+ PSP_DEBUG_PRINT("Done with relocation. extendedHi16=%d\n\n", extendedHi16);
free(rel);
return true;
}
bool DLObject::readElfHeader(int fd, Elf32_Ehdr *ehdr) {
+ DEBUG_ENTER_FUNC();
// Start reading the elf header. Check for errors
if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr) ||
memcmp(ehdr->e_ident, ELFMAG, SELFMAG) || // Check MAGIC
@@ -275,31 +274,32 @@ bool DLObject::readElfHeader(int fd, Elf32_Ehdr *ehdr) {
ehdr->e_machine != EM_MIPS || // Check for MIPS machine type
ehdr->e_phentsize < sizeof(Elf32_Phdr) || // Check for size of program header
ehdr->e_shentsize != sizeof(Elf32_Shdr)) { // Check for size of section header
- seterror("Invalid file type.");
+ PSP_ERROR("Invalid file type.");
return false;
}
- DBG("phoff = %d, phentsz = %d, phnum = %d\n",
+ PSP_DEBUG_PRINT("phoff = %d, phentsz = %d, phnum = %d\n",
ehdr->e_phoff, ehdr->e_phentsize, ehdr->e_phnum);
return true;
}
bool DLObject::readProgramHeaders(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, int num) {
+ DEBUG_ENTER_FUNC();
// Read program header
if (lseek(fd, ehdr->e_phoff + sizeof(*phdr)*num, SEEK_SET) < 0 ||
read(fd, phdr, sizeof(*phdr)) != sizeof(*phdr)) {
- seterror("Program header load failed.");
+ PSP_ERROR("Program header load failed.");
return false;
}
// Check program header values
if (phdr->p_type != PT_LOAD || phdr->p_filesz > phdr->p_memsz) {
- seterror("Invalid program header.");
+ PSP_ERROR("Invalid program header.");
return false;
}
- DBG("offs = %x, filesz = %x, memsz = %x, align = %x\n",
+ PSP_DEBUG_PRINT("offs = %x, filesz = %x, memsz = %x, align = %x\n",
phdr->p_offset, phdr->p_filesz, phdr->p_memsz, phdr->p_align);
return true;
@@ -307,6 +307,7 @@ bool DLObject::readProgramHeaders(int fd, Elf32_Ehdr *ehdr, Elf32_Phdr *phdr, in
}
bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) {
+ DEBUG_ENTER_FUNC();
char *baseAddress = 0;
@@ -315,15 +316,15 @@ bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) {
// Attempt to allocate memory for segment
int extra = phdr->p_vaddr % phdr->p_align; // Get extra length TODO: check logic here
- DBG("extra mem is %x\n", extra);
+ PSP_DEBUG_PRINT("extra mem is %x\n", extra);
if (phdr->p_align < 0x10000) phdr->p_align = 0x10000; // Fix for wrong alignment on e.g. AGI
if (!(_segment = (char *)memalign(phdr->p_align, phdr->p_memsz + extra))) {
- seterror("Out of memory.\n");
+ PSP_ERROR("Out of memory.\n");
return false;
}
- DBG("allocated segment @ %p\n", _segment);
+ PSP_DEBUG_PRINT("allocated segment @ %p\n", _segment);
// Get offset to load segment into
baseAddress = (char *)_segment + phdr->p_vaddr;
@@ -332,20 +333,20 @@ bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) {
_shortsSegment = ShortsMan.newSegment(phdr->p_memsz, (char *)phdr->p_vaddr);
baseAddress = _shortsSegment->getStart();
- DBG("shorts segment @ %p to %p. Segment wants to be at %x. Offset=%x\n",
+ PSP_DEBUG_PRINT("shorts segment @ %p to %p. Segment wants to be at %x. Offset=%x\n",
_shortsSegment->getStart(), _shortsSegment->getEnd(), phdr->p_vaddr, _shortsSegment->getOffset());
}
// Set bss segment to 0 if necessary (assumes bss is at the end)
if (phdr->p_memsz > phdr->p_filesz) {
- DBG("Setting %p to %p to 0 for bss\n", baseAddress + phdr->p_filesz, baseAddress + phdr->p_memsz);
+ PSP_DEBUG_PRINT("Setting %p to %p to 0 for bss\n", baseAddress + phdr->p_filesz, baseAddress + phdr->p_memsz);
memset(baseAddress + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
}
// Read the segment into memory
if (lseek(fd, phdr->p_offset, SEEK_SET) < 0 ||
read(fd, baseAddress, phdr->p_filesz) != (ssize_t)phdr->p_filesz) {
- seterror("Segment load failed.");
+ PSP_ERROR("Segment load failed.");
return false;
}
@@ -354,12 +355,13 @@ bool DLObject::loadSegment(int fd, Elf32_Phdr *phdr) {
Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) {
+ DEBUG_ENTER_FUNC();
Elf32_Shdr *shdr = NULL;
// Allocate memory for section headers
if (!(shdr = (Elf32_Shdr *)malloc(ehdr->e_shnum * sizeof(*shdr)))) {
- seterror("Out of memory.");
+ PSP_ERROR("Out of memory.");
return NULL;
}
@@ -367,7 +369,7 @@ Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) {
if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0 ||
read(fd, shdr, ehdr->e_shnum * sizeof(*shdr)) !=
(ssize_t)(ehdr->e_shnum * sizeof(*shdr))) {
- seterror("Section headers load failed.");
+ PSP_ERROR("Section headers load failed.");
return NULL;
}
@@ -375,11 +377,12 @@ Elf32_Shdr * DLObject::loadSectionHeaders(int fd, Elf32_Ehdr *ehdr) {
}
int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
+ DEBUG_ENTER_FUNC();
// Loop over sections, looking for symbol table linked to a string table
for (int i = 0; i < ehdr->e_shnum; i++) {
- //DBG("Section %d: type = %x, size = %x, entsize = %x, link = %x\n",
- // i, shdr[i].sh_type, shdr[i].sh_size, shdr[i].sh_entsize, shdr[i].sh_link);
+ PSP_DEBUG_PRINT("Section %d: type = %x, size = %x, entsize = %x, link = %x\n",
+ i, shdr[i].sh_type, shdr[i].sh_size, shdr[i].sh_entsize, shdr[i].sh_link);
if (shdr[i].sh_type == SHT_SYMTAB &&
shdr[i].sh_entsize == sizeof(Elf32_Sym) &&
@@ -392,15 +395,15 @@ int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
// Check for no symbol table
if (_symtab_sect < 0) {
- seterror("No symbol table.");
+ PSP_ERROR("No symbol table.");
return -1;
}
- DBG("Symbol section at section %d, size %x\n", _symtab_sect, shdr[_symtab_sect].sh_size);
+ PSP_DEBUG_PRINT("Symbol section at section %d, size %x\n", _symtab_sect, shdr[_symtab_sect].sh_size);
// Allocate memory for symbol table
if (!(_symtab = malloc(shdr[_symtab_sect].sh_size))) {
- seterror("Out of memory.");
+ PSP_ERROR("Out of memory.");
return -1;
}
@@ -408,25 +411,26 @@ int DLObject::loadSymbolTable(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
if (lseek(fd, shdr[_symtab_sect].sh_offset, SEEK_SET) < 0 ||
read(fd, _symtab, shdr[_symtab_sect].sh_size) !=
(ssize_t)shdr[_symtab_sect].sh_size) {
- seterror("Symbol table load failed.");
+ PSP_ERROR("Symbol table load failed.");
return -1;
}
// Set number of symbols
_symbol_cnt = shdr[_symtab_sect].sh_size / sizeof(Elf32_Sym);
- DBG("Loaded %d symbols.\n", _symbol_cnt);
+ PSP_DEBUG_PRINT("Loaded %d symbols.\n", _symbol_cnt);
return _symtab_sect;
}
bool DLObject::loadStringTable(int fd, Elf32_Shdr *shdr) {
+ DEBUG_ENTER_FUNC();
int string_sect = shdr[_symtab_sect].sh_link;
// Allocate memory for string table
if (!(_strtab = (char *)malloc(shdr[string_sect].sh_size))) {
- seterror("Out of memory.");
+ PSP_ERROR("Out of memory.");
return false;
}
@@ -434,16 +438,17 @@ bool DLObject::loadStringTable(int fd, Elf32_Shdr *shdr) {
if (lseek(fd, shdr[string_sect].sh_offset, SEEK_SET) < 0 ||
read(fd, _strtab, shdr[string_sect].sh_size) !=
(ssize_t)shdr[string_sect].sh_size) {
- seterror("Symbol table strings load failed.");
+ PSP_ERROR("Symbol table strings load failed.");
return false;
}
return true;
}
void DLObject::relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset) {
+ DEBUG_ENTER_FUNC();
int shortsCount = 0, othersCount = 0;
- DBG("Relocating symbols by %x. Shorts offset=%x\n", offset, shortsOffset);
+ PSP_DEBUG_PRINT("Relocating symbols by %x. Shorts offset=%x\n", offset, shortsOffset);
// Loop over symbols, add relocation offset
Elf32_Sym *s = (Elf32_Sym *)_symtab;
@@ -454,22 +459,23 @@ void DLObject::relocateSymbols(Elf32_Addr offset, Elf32_Addr shortsOffset) {
othersCount++;
s->st_value += offset;
if (s->st_value < (Elf32_Addr)_segment || s->st_value > (Elf32_Addr)_segment + _segmentSize)
- seterror("Symbol out of bounds! st_value = %x\n", s->st_value);
+ PSP_ERROR("Symbol out of bounds! st_value = %x\n", s->st_value);
} else { // shorts section
shortsCount++;
s->st_value += shortsOffset;
if (!_shortsSegment->inSegment((char *)s->st_value))
- seterror("Symbol out of bounds! st_value = %x\n", s->st_value);
+ PSP_ERROR("Symbol out of bounds! st_value = %x\n", s->st_value);
}
}
}
- DBG("Relocated %d short symbols, %d others.\n", shortsCount, othersCount);
+ PSP_DEBUG_PRINT("Relocated %d short symbols, %d others.\n", shortsCount, othersCount);
}
bool DLObject::relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
+ DEBUG_ENTER_FUNC();
// Loop over sections, finding relocation sections
for (int i = 0; i < ehdr->e_shnum; i++) {
@@ -500,7 +506,7 @@ bool DLObject::relocateRels(int fd, Elf32_Ehdr *ehdr, Elf32_Shdr *shdr) {
bool DLObject::load(int fd) {
- fprintf(stderr, "In DLObject::load\n");
+ DEBUG_ENTER_FUNC();
Elf32_Ehdr ehdr; // ELF header
Elf32_Phdr phdr; // Program header
@@ -512,8 +518,7 @@ bool DLObject::load(int fd) {
}
for (int i = 0; i < ehdr.e_phnum; i++) { // Load our 2 segments
-
- fprintf(stderr, "Loading segment %d\n", i);
+ PSP_DEBUG_PRINT("Loading segment %d\n", i);
if (readProgramHeaders(fd, &ehdr, &phdr, i) == false)
return false;
@@ -543,19 +548,20 @@ bool DLObject::load(int fd) {
}
bool DLObject::open(const char *path) {
+ DEBUG_ENTER_FUNC();
int fd;
void *ctors_start, *ctors_end;
- DBG("open(\"%s\")\n", path);
+ PSP_DEBUG_PRINT("open(\"%s\")\n", path);
// Get the address of the global pointer
_gpVal = (unsigned int) & _gp;
- DBG("_gpVal is %x\n", _gpVal);
+ PSP_DEBUG_PRINT("_gpVal is %x\n", _gpVal);
PowerMan.beginCriticalSection();
if ((fd = ::open(path, O_RDONLY)) < 0) {
- seterror("%s not found.", path);
+ PSP_ERROR("%s not found.", path);
return false;
}
@@ -581,21 +587,22 @@ bool DLObject::open(const char *path) {
if (ctors_start == NULL || ctors_end == NULL || _dtors_start == NULL ||
_dtors_end == NULL) {
- seterror("Missing ctors/dtors.");
+ PSP_ERROR("Missing ctors/dtors.");
_dtors_start = _dtors_end = NULL;
unload();
return false;
}
- DBG("Calling constructors.\n");
+ PSP_DEBUG_PRINT("Calling constructors.\n");
for (void (**f)(void) = (void (**)(void))ctors_start; f != ctors_end; f++)
(**f)();
- DBG("%s opened ok.\n", path);
+ PSP_DEBUG_PRINT("%s opened ok.\n", path);
return true;
}
bool DLObject::close() {
+ DEBUG_ENTER_FUNC();
if (_dtors_start != NULL && _dtors_end != NULL)
for (void (**f)(void) = (void (**)(void))_dtors_start; f != _dtors_end; f++)
(**f)();
@@ -605,10 +612,11 @@ bool DLObject::close() {
}
void *DLObject::symbol(const char *name) {
- DBG("symbol(\"%s\")\n", name);
+ DEBUG_ENTER_FUNC();
+ PSP_DEBUG_PRINT("symbol(\"%s\")\n", name);
if (_symtab == NULL || _strtab == NULL || _symbol_cnt < 1) {
- seterror("No symbol table loaded.");
+ PSP_ERROR("No symbol table loaded.");
return NULL;
}
@@ -621,23 +629,25 @@ void *DLObject::symbol(const char *name) {
!strcmp(name, _strtab + s->st_name)) {
// We found the symbol
- DBG("=> %p\n", (void*)s->st_value);
+ PSP_DEBUG_PRINT("=> %p\n", (void*)s->st_value);
return (void*)s->st_value;
}
}
- seterror("Symbol \"%s\" not found.", name);
+ PSP_ERROR("Symbol \"%s\" not found.", name);
return NULL;
}
ShortSegmentManager::ShortSegmentManager() {
+ DEBUG_ENTER_FUNC();
_shortsStart = &__plugin_hole_start ;
_shortsEnd = &__plugin_hole_end;
}
ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *origAddr) {
+ DEBUG_ENTER_FUNC();
char *lastAddress = origAddr;
Common::List<Segment *>::iterator i;
@@ -654,7 +664,7 @@ ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *or
lastAddress += 4 - ((Elf32_Addr)lastAddress & 3); // Round up to multiple of 4
if (lastAddress + size > _shortsEnd) {
- seterror("Error. No space in shorts segment for %x bytes. Last address is %p, max address is %p.\n",
+ PSP_ERROR("No space in shorts segment for %x bytes. Last address is %p, max address is %p.\n",
size, lastAddress, _shortsEnd);
return NULL;
}
@@ -665,14 +675,15 @@ ShortSegmentManager::Segment *ShortSegmentManager::newSegment(int size, char *or
_list.insert(i, seg);
- DBG("Shorts segment size %x allocated. End = %p. Remaining space = %x. Highest so far is %p.\n",
+ PSP_DEBUG_PRINT("Shorts segment size %x allocated. End = %p. Remaining space = %x. Highest so far is %p.\n",
size, lastAddress + size, _shortsEnd - _list.back()->getEnd(), _highestAddress);
return seg;
}
void ShortSegmentManager::deleteSegment(ShortSegmentManager::Segment *seg) {
- DBG("Deleting shorts segment from %p to %p.\n\n", seg->getStart(), seg->getEnd());
+ DEBUG_ENTER_FUNC();
+ PSP_DEBUG_PRINT("Deleting shorts segment from %p to %p.\n\n", seg->getStart(), seg->getEnd());
_list.remove(seg);
delete seg;
}
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/platform/PalmOS/Src/cd_msa.h b/backends/platform/psp/rtc.h
index 223bc0efcf..7c1a28474d 100644
--- a/backends/platform/PalmOS/Src/cd_msa.h
+++ b/backends/platform/psp/rtc.h
@@ -18,51 +18,33 @@
* along 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/osys_psp.cpp $
+ * $Id: osys_psp.cpp 49903 2010-06-16 09:04:27Z Bluddy $
*
*/
-#ifndef CD_MSA_H
-#define CD_MSA_H
-
-#include "cdaudio.h"
-
-class MsaCDPlayer : public CDAudio {
+#ifndef _PSP_RTC_H_
+#define _PSP_RTC_H_
+
+#include "common/singleton.h"
+
+class PspRtc : public Common::Singleton<PspRtc> {
+private:
+ 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:
- 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);
-
- private:
- void initInternal();
-
- OSystem *_sys;
- UInt16 _msaRefNum;
-
- UInt32 _volumeLLimit;
- UInt32 _volumeRLimit;
-
- // cdrom
- AlbumInfoType _msaAlbum;
- UInt16 _msaLoops;
-
- UInt32 _msaStopTime;
-
- UInt32 _msaStartFrame;
- UInt32 _msaDuration;
-
- UInt16 _msaTrack;
- UInt32 _msaTrackStartSu, _msaTrackEndSu;
- UInt32 _msaTrackLength;
+ PspRtc()
+ : _startMillis(0), _startMicros(0),
+ _lastMillis(0), _milliOffset(0),
+ _looped(false) {
+ init();
+ }
+ void init();
+ uint32 getMillis();
+ uint32 getMicros();
};
-#endif
+#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/init_palmos.h b/backends/platform/psp/tests.h
index d4691dd15b..1518acfb4c 100644
--- a/backends/platform/PalmOS/Src/init_palmos.h
+++ b/backends/platform/psp/tests.h
@@ -18,25 +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 INIT_PALMOS_H
-#define INIT_PALMOS_H
+#ifndef _PSP_TESTS_H_
+#define _PSP_TESTS_H_
-#define PALM_PORTRAIT 1
-#define PALM_LANDSCAPE 2
-
-void PalmInit(UInt8 init);
-void PalmRelease(UInt8 init);
-
-Err PalmHRInit(UInt32 depth);
-void PalmHRRelease();
-
-
-UInt8 PalmScreenSize(Coord *stdw, Coord *stdh, Coord *fullw, Coord *fullh);
-void PalmGetMemory(UInt32* storageMemoryP, UInt32* dynamicMemoryP, UInt32 *storageFreeP, UInt32 *dynamicFreeP);
+//#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
index 4e7d5eada9..916b1e553b 100644
--- a/backends/platform/psp/thread.cpp
+++ b/backends/platform/psp/thread.cpp
@@ -23,14 +23,56 @@
*
*/
-#include <time.h>
-#include <psptypes.h>
-#include <psprtc.h>
#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);
}
@@ -39,49 +81,154 @@ void PspThread::delayMicros(uint32 us) {
sceKernelDelayThread(us);
}
-void PspRtc::init() { // init our starting ticks
- uint32 ticks[2];
- sceRtcGetCurrentTick((u64 *)ticks);
+// Class PspSemaphore ------------------------------------------------
+//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
+//#define __PSP_DEBUG_PRINT__ /* For debug printouts */
+
+#include "backends/platform/psp/trace.h"
- _startMillis = ticks[0]/1000;
- _startMicros = ticks[0];
- //_lastMillis = ticks[0]/1000; //debug - only when we don't subtract startMillis
+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");
}
-#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 */
+PspSemaphore::~PspSemaphore() {
+ DEBUG_ENTER_FUNC();
+ if (_handle)
+ if (sceKernelDeleteSema((SceUID)_handle) < 0)
+ PSP_ERROR("failed to delete semaphore.\n");
+}
-// 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];
+int PspSemaphore::numOfWaitingThreads() {
+ DEBUG_ENTER_FUNC();
+ SceKernelSemaInfo info;
+ info.numWaitThreads = 0;
- sceRtcGetCurrentTick((u64 *)ticks); // can introduce weird thread delays
+ 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;
- uint32 millis = ticks[0]/1000;
- millis -= _startMillis; // get ms since start of program
+ if (sceKernelReferSemaStatus((SceUID)_handle, &info) < 0)
+ PSP_ERROR("failed to retrieve semaphore info for handle %d\n", _handle);
+
+ return info.currentCount;
+}
- 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;
- }
+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();
- _lastMillis = millis;
+ if (sceKernelSignalSema((SceUID)_handle, num) < 0)
+ return false;
+ return true;
+}
+
+// Class PspMutex ------------------------------------------------------------
+
+bool PspMutex::lock() {
+ DEBUG_ENTER_FUNC();
+ int threadId = sceKernelGetThreadId();
+ bool ret = true;
- return millis + _milliOffset;
+ if (_ownerId == threadId) {
+ _recursiveCount++;
+ } else {
+ ret = _semaphore.take();
+ _ownerId = threadId;
+ _recursiveCount = 0;
+ }
+ return ret;
}
-uint32 PspRtc::getMicros() {
- uint32 ticks[2];
+bool PspMutex::unlock() {
+ DEBUG_ENTER_FUNC();
+ int threadId = sceKernelGetThreadId();
+ bool ret = true;
- sceRtcGetCurrentTick((u64 *)ticks);
- ticks[0] -= _startMicros;
+ if (_ownerId != threadId) {
+ PSP_ERROR("attempt to unlock mutex by thread[%x] as opposed to owner[%x]\n",
+ threadId, _ownerId);
+ return false;
+ }
- return ticks[0];
+ 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
index 380159fa2d..de1c10a2aa 100644
--- a/backends/platform/psp/thread.h
+++ b/backends/platform/psp/thread.h
@@ -26,26 +26,69 @@
#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 void delayMillis(uint32 ms);
+public:
+ // static functions
+ static void delayMillis(uint32 ms); // delay the current thread
static void delayMicros(uint32 us);
};
-class PspRtc {
+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:
- uint32 _startMillis;
- uint32 _startMicros;
- uint32 _lastMillis;
- uint32 _milliOffset; // to prevent looping around of millis
- bool _looped; // make sure we only loop once
+ PspMutex _mutex;
+ int _waitingThreads;
+ int _signaledThreads;
+ PspSemaphore _waitSem;
+ PspSemaphore _doneSem;
public:
- PspRtc() : _startMillis(0), _startMicros(0), _lastMillis(0), _milliOffset(0), _looped(false) { init(); }
- void init();
- uint32 getMillis();
- uint32 getMicros();
+ PspCondition() : _mutex(true), _waitingThreads(0), _signaledThreads(0),
+ _waitSem(0), _doneSem(0) {}
+ void wait(PspMutex &externalMutex);
+ void releaseAll();
};
enum ThreadPriority {
@@ -57,6 +100,7 @@ enum ThreadPriority {
};
enum StackSizes {
+ STACK_DEFAULT = 4 * 1024,
STACK_AUDIO_THREAD = 16 * 1024,
STACK_TIMER_THREAD = 32 * 1024,
STACK_DISPLAY_THREAD = 2 * 1024,
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 82670cfcb7..a97a153f3c 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 13e614a4a2..52bbb59165 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 f8ae824acf..6686249416 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 341a59c8cf..5c901ba711 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.
@@ -274,6 +274,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/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/psp/psp-provider.cpp b/backends/plugins/psp/psp-provider.cpp
index f394916538..5760424cbf 100644
--- a/backends/plugins/psp/psp-provider.cpp
+++ b/backends/plugins/psp/psp-provider.cpp
@@ -31,6 +31,8 @@
#include "backends/platform/psp/psploader.h"
+#include "backends/platform/psp/trace.h"
+
class PSPPlugin : public DynamicPlugin {
protected:
@@ -95,13 +97,13 @@ Plugin* PSPPluginProvider::createPlugin(const Common::FSNode &node) const {
bool PSPPluginProvider::isPluginFilename(const Common::FSNode &node) const {
// Check the plugin suffix
Common::String filename = node.getName();
- fprintf(stderr, "Testing name %s", filename.c_str());
+ PSP_DEBUG_PRINT("Testing name %s", filename.c_str());
if (!filename.hasSuffix(".PLG") && !filename.hasSuffix(".plg")) {
- fprintf(stderr," fail.\n");
+ PSP_DEBUG_PRINT(" fail.\n");
return false;
}
- fprintf(stderr," success!\n");
+ PSP_DEBUG_PRINT(" success!\n");
return true;
}
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 1c548d3f50..2f4e78fd80 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__) || defined(ANDROID)
+#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")
@@ -948,7 +944,7 @@ Common::Error processSettings(Common::String &command, Common::StringMap &settin
// 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__) && !defined(ANDROID)
+#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 bfb6611a91..e651456ace 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... ");
GameDescriptor game = EngineMan.findGame(gameid, &plugin);
if (plugin == 0) {
@@ -141,7 +143,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(),
@@ -200,7 +202,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
@@ -268,22 +270,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);
@@ -319,6 +321,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
@@ -338,6 +342,16 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
// Load the plugins.
PluginManager::instance().loadPlugins();
+ // 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.
Common::Error res;
@@ -387,7 +401,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
@@ -413,8 +427,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 feead28247..f82f1d64d2 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -170,14 +170,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__)
@@ -193,13 +194,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
@@ -207,6 +201,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 7aff8d40b9..58343114a2 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 6a6a818083..df7351d55a 100644
--- a/common/macresman.cpp
+++ b/common/macresman.cpp
@@ -525,12 +525,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
@@ -616,21 +614,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 189c37adb4..e3dec6cdc2 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 11041fa3ce..5e0d7149b0 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 87ba55ebf1..0d0b0aead9 100644
--- a/common/textconsole.cpp
+++ b/common/textconsole.cpp
@@ -47,6 +47,10 @@ extern bool isSmartphone();
#include <android/log.h>
#endif
+#ifdef __PSP__
+ #include "backends/platform/psp/trace.h"
+#endif
+
namespace Common {
static OutputFormatter s_errorOutputFormatter = 0;
@@ -151,14 +155,14 @@ void NORETURN_PRE error(const char *s, ...) {
__android_log_assert("Fatal error", "ScummVM", "%s", buf_output);
#endif
-#ifdef PALMOS_MODE
- extern void PalmFatalError(const char *err);
- PalmFatalError(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 e46106025e..a29518a796 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 b3a95adf55..d74efa5eaa 100755
--- a/configure
+++ b/configure
@@ -120,6 +120,7 @@ _tremor=auto
_flac=auto
_mad=auto
_alsa=auto
+_seq_midi=auto
_zlib=auto
_mpeg2=no
_fluidsynth=auto
@@ -134,9 +135,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
@@ -266,6 +270,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"
@@ -286,15 +294,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
}
@@ -342,7 +363,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)
@@ -626,7 +647,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:
@@ -656,7 +677,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
@@ -677,6 +698,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
@@ -738,6 +760,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 ;;
@@ -761,6 +785,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 ;;
@@ -896,6 +922,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
@@ -907,6 +938,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
@@ -945,10 +981,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
@@ -1000,11 +1036,6 @@ wince)
_host_cpu=arm
_host_alias=arm-wince-mingw32ce
;;
-android)
- _host_os=android
- _host_cpu=arm
- _host_alias=arm-android-eabi
- ;;
*)
if test -n "$_host"; then
guessed_host=`$_srcdir/config.sub $_host`
@@ -1038,7 +1069,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
@@ -1064,12 +1097,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>"
@@ -1083,12 +1128,6 @@ psp)
exit 1
fi
;;
-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
- ;;
*)
;;
esac
@@ -1132,9 +1171,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
@@ -1314,55 +1356,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
@@ -1370,7 +1435,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"
@@ -1378,14 +1443,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
@@ -1396,30 +1463,27 @@ 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"
DEFINES="$DEFINES -D_WIN32_WCE=300 -D__ARM__ -D_ARM_ -DUNICODE -DFPM_DEFAULT -DNONSTANDARD_PORT"
DEFINES="$DEFINES -DWIN32 -Dcdecl= -D__cdecl__="
;;
- android)
- DEFINES="$DEFINES -DUNIX"
- 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"
- ;;
# 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
@@ -1427,8 +1491,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'
@@ -1437,7 +1514,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*)
@@ -1452,18 +1530,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'
@@ -1472,10 +1568,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'
@@ -1483,14 +1580,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'
@@ -1498,24 +1598,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
@@ -1528,8 +1634,9 @@ if test -n "$_host"; then
_need_memalign=yes
;;
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'
@@ -1537,14 +1644,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'
@@ -1552,36 +1661,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
@@ -1590,16 +1705,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.
@@ -1619,14 +1735,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'
@@ -1634,14 +1751,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"
@@ -1661,22 +1778,9 @@ 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"
;;
- android)
- DEFINES="$DEFINES -DANDROID -DUNIX -DUSE_ARM_SMUSH_ASM"
- _endian=little
- _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"
- _build_hq_scalers="no"
- ;;
*)
echo "WARNING: Unknown target, continuing with auto-detected values"
;;
@@ -1753,21 +1857,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'
-add_to_config_h_if_yes $_need_memalign '#define SCUMM_NEED_ALIGNMENT'
+define_in_config_h_if_yes $_need_memalign 'SCUMM_NEED_ALIGNMENT'
+
+if test "$_unix" = yes ; then
+ DEFINES="$DEFINES -DUNIX"
+fi
#
# Check whether to enable a verbose build
@@ -1901,7 +2009,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
'
@@ -1919,40 +2027,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
@@ -1960,17 +2050,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
@@ -1978,7 +2063,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
@@ -1994,13 +2079,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"
#
@@ -2017,15 +2099,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"
@@ -2049,17 +2131,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"
#
@@ -2075,13 +2154,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"
#
@@ -2097,15 +2173,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"
@@ -2119,13 +2206,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"
#
@@ -2165,13 +2249,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"
#
@@ -2187,7 +2268,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"
@@ -2197,9 +2277,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"
#
@@ -2219,12 +2298,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
@@ -2232,18 +2312,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
@@ -2301,8 +2375,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
@@ -2314,6 +2387,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
#
@@ -2379,11 +2476,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`"
@@ -2408,8 +2543,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"
@@ -2424,14 +2563,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
@@ -2462,14 +2595,6 @@ case $_backend in
INCLUDES="$INCLUDES "'-I$(srcdir) -I$(srcdir)/backends/platform/wince -I$(srcdir)/engines -I$(srcdir)/backends/platform/wince/missing/gcc -I$(srcdir)/backends/platform/wince/CEgui -I$(srcdir)/backends/platform/wince/CEkeys'
LIBS="$LIBS -static -lSDL"
;;
- android)
- # -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="$LIBS -lgcc -lstdc++ -llog -lGLESv1_CM -lEGL"
- DEFINES="$DEFINES -D__ANDROID__ -DANDROID_BACKEND -DREDUCE_MEMORY_USAGE"
- add_line_to_config_mk 'PLUGIN_LDFLAGS += $(LDFLAGS) -Wl,-shared,-Bsymbolic'
- ;;
*)
echo "support for $_backend backend not implemented in configure script yet"
exit 1
@@ -2485,7 +2610,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* | android)
+ amigaos* | android | ds | dreamcast | gamecube | mingw* | n64 | psp | wii | wince )
CXXFLAGS="$CXXFLAGS -W -Wno-unused-parameter"
;;
*)
@@ -2506,7 +2631,7 @@ fi;
# Some platforms use certain GNU extensions in header files
case $_host_os in
-gamecube | psp | wii | android)
+android | gamecube | psp | wii)
;;
*)
CXXFLAGS="$CXXFLAGS -pedantic"
@@ -2614,25 +2739,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
index 00d15f561e..62caa64a55 100644..100755
--- a/dists/android/mkmanifest.pl
+++ b/dists/android/mkmanifest.pl
@@ -105,6 +105,7 @@ sub print_manifest {
'package' => "org.inodes.gus.scummvm.plugin.$info->{name}",
[ANDROID, 'versionCode'] => $package_versionCode,
[ANDROID, 'versionName'] => $package_versionName,
+ [ANDROID, 'installLocation'] => 'preferExternal',
);
$writer->startTag(
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/engine-data/kyra.dat b/dists/engine-data/kyra.dat
index 3fba5780f4..ff21159362 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/cine.cpp b/engines/cine/cine.cpp
index c50af52901..e6ac2859cf 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;
@@ -147,9 +145,9 @@ void CineEngine::initialize() {
_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;
@@ -163,13 +161,13 @@ void CineEngine::initialize() {
// Its size will change when loading data into it with the loadPart function.
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");
}
diff --git a/engines/cine/cine.h b/engines/cine/cine.h
index 6f7b409ad7..6f2c2243e2 100644
--- a/engines/cine/cine.h
+++ b/engines/cine/cine.h
@@ -190,8 +190,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..1f747c5a01 100644
--- a/engines/cine/gfx.cpp
+++ b/engines/cine/gfx.cpp
@@ -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.
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/saveload.cpp b/engines/cine/saveload.cpp
index c76bed3f8e..f9dfcc7737 100644
--- a/engines/cine/saveload.cpp
+++ b/engines/cine/saveload.cpp
@@ -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,7 +566,7 @@ bool CineEngine::loadTempSaveOS(Common::SeekableReadStream &in) {
}
loadObjectTable(in);
- renderer->restorePalette(in);
+ renderer->restorePalette(in, hdr.version);
globalVars.load(in, NUM_MAX_VAR);
loadZoneData(in);
loadCommandVariables(in);
@@ -698,7 +698,7 @@ 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);
@@ -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);
@@ -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);
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/various.cpp b/engines/cine/various.cpp
index 9a10c2b5d7..82c40a2f50 100644
--- a/engines/cine/various.cpp
+++ b/engines/cine/various.cpp
@@ -450,7 +450,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;
diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp
index e6d0359059..2f38aa98ba 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");
diff --git a/engines/cruise/cruise_main.cpp b/engines/cruise/cruise_main.cpp
index 14de916a84..65d8b57366 100644
--- a/engines/cruise/cruise_main.cpp
+++ b/engines/cruise/cruise_main.cpp
@@ -1833,19 +1833,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/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/vars.cpp b/engines/cruise/vars.cpp
index 94fd00cbfd..bab5d171fd 100644
--- a/engines/cruise/vars.cpp
+++ b/engines/cruise/vars.cpp
@@ -64,11 +64,7 @@ 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 1e19794f3a..3cb09602cc 100644
--- a/engines/cruise/vars.h
+++ b/engines/cruise/vars.h
@@ -167,12 +167,7 @@ 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;
diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp
index 954bc81470..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"
@@ -85,37 +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);
// 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", "Help", kHelpCmd, 'H');
+ _helpButton = new GUI::ButtonWidget(this, "GlobalMenu.Help", _("~H~elp"), 0, kHelpCmd);
_helpButton->setEnabled(false);
- new GUI::ButtonWidget(this, "GlobalMenu.About", "About", kAboutCmd, 'A');
+ new GUI::ButtonWidget(this, "GlobalMenu.About", _("~A~bout"), 0, kAboutCmd);
- _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", "Return to Launcher", kRTLCmd, 'R');
+ _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);
}
@@ -297,11 +298,11 @@ ConfigDialog::ConfigDialog(bool subtitleControls)
// Add the buttons
//
- new GUI::ButtonWidget(this, "GlobalConfig.Ok", "OK", GUI::kOKCmd, 'O');
- new GUI::ButtonWidget(this, "GlobalConfig.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, "GlobalConfig.Keys", "Keys", kKeysCmd, 'K');
+ new GUI::ButtonWidget(this, "GlobalConfig.Keys", _("~K~eys"), 0, kKeysCmd);
_keysDialog = NULL;
#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 e4bd844d75..d6a3bafd9f 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 2c3ca63600..7e9f68a355 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 {
@@ -115,6 +116,8 @@ DrasculaEngine::~DrasculaEngine() {
freeRoomsTable();
+ delete _console;
+
free(_charMap);
free(_itemLocations);
free(_polX);
@@ -173,6 +176,8 @@ Common::Error DrasculaEngine::run() {
_lang = kEnglish;
}
+ _console = new Console(this);
+
if (!loadDrasculaDat())
return Common::kUnknownError;
@@ -241,6 +246,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);
@@ -272,6 +279,7 @@ Common::Error DrasculaEngine::run() {
loadPic(974, tableSurface);
if (currentChapter != 2) {
+ loadPic(99, cursorSurface);
loadPic(99, backSurface);
loadPic(97, extraSurface);
}
@@ -499,11 +507,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
@@ -524,18 +536,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();
@@ -594,6 +612,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);
}
@@ -741,10 +762,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
@@ -758,11 +779,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 13c8a742ca..73aea7b7f2 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/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/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/inter_playtoons.cpp b/engines/gob/inter_playtoons.cpp
index c9b962579b..142467b47f 100644
--- a/engines/gob/inter_playtoons.cpp
+++ b/engines/gob/inter_playtoons.cpp
@@ -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..9e841e7e68 100644
--- a/engines/gob/inter_v1.cpp
+++ b/engines/gob/inter_v1.cpp
@@ -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))
@@ -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/mult_v2.cpp b/engines/gob/mult_v2.cpp
index 88b604023c..6acd096e58 100644
--- a/engines/gob/mult_v2.cpp
+++ b/engines/gob/mult_v2.cpp
@@ -1149,7 +1149,6 @@ void Mult_v2::playImd(const char *imdFile, Mult::Mult_ImdKey &key, int16 dir,
void Mult_v2::advanceObjects(int16 index) {
int16 frame;
bool stop = false;
- bool hasImds = false;
frame = _multData->animKeysFrames[index];
if (frame == -1)
@@ -1254,7 +1253,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/videoplayer.cpp b/engines/gob/videoplayer.cpp
index 125edd4307..51bc1b88a5 100644
--- a/engines/gob/videoplayer.cpp
+++ b/engines/gob/videoplayer.cpp
@@ -73,7 +73,7 @@ bool VideoPlayer::Video::open(const char *fileName, Type which, int16 width, int
return false;
}
- if (!_video->load(*_stream)) {
+ if (!_video->load(_stream)) {
warning("While loading video \"%s\"", fileName);
close();
return false;
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..fe4cc7298f
--- /dev/null
+++ b/engines/kyra/detection_tables.h
@@ -0,0 +1,1192 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along 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, "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..98f0e31b69 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);
}
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..95e2a5e63f 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,39 @@
#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->cdaSetVolume(1, 118, 118);
+
+ return true;
}
void SoundTowns::process() {
@@ -3816,10 +92,13 @@ void SoundTowns::playTrack(uint8 track) {
beginFadeOut();
if (_musicEnabled == 2 && trackNum != -1) {
+ _driver->cdaSetVolume(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 +108,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 +130,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 +158,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 +200,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->cdaSetVolume(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->cdaSetVolume(1, i, i);
+ _vm->delay(2 * _vm->tickLength());
+ }
-int SoundTowns::open() {
- if (!_driver)
- return 255;
+ for (int i = 83; i > 58; i -= 2) {
+ _driver->cdaSetVolume(1, i, i);
+ _vm->delay(_vm->tickLength());
+ }
- int ret = _driver->open();
- if (ret)
- return ret;
+ for (int i = 58; i > 0; i--)
+ _driver->cdaSetVolume(1, i, i);
- _driver->setTimerCallback(this, &onTimer);
- return 0;
-}
+ _driver->cdaSetVolume(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->chanLevel(i, *src++);
+ for (int i = 0; i < 32; i++)
+ _driver->chanTranspose(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 +381,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 +457,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 +483,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 +507,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 +584,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 +605,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 +645,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 +662,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..274acae22c 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 71
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..dbf6808e37
--- /dev/null
+++ b/engines/kyra/staticres_lol.cpp
@@ -0,0 +1,882 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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 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;
+}
+
+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 1142ba48d1..37314eff44 100644
--- a/engines/m4/animation.cpp
+++ b/engines/m4/animation.cpp
@@ -44,6 +44,7 @@ MadsAnimation::MadsAnimation(MadsM4Engine *vm, MadsView *view): Animation(vm), _
_currentFrame = 0;
_oldFrameEntry = 0;
_nextFrameTimer = _madsVm->_currentTimer;
+ _nextScrollTimer = 0;
}
MadsAnimation::~MadsAnimation() {
@@ -56,14 +57,14 @@ MadsAnimation::~MadsAnimation() {
if (_field12) {
_view->_spriteSlots.deleteSprites(_spriteListIndexes[_spriteListIndex]);
}
-
- delete _font;
}
+#define FILENAME_SIZE 13
+
/**
* Initialises and loads the data of an animation
*/
-void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4Surface *interfaceSurface, M4Surface *sceneSurface) {
+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];
@@ -87,34 +88,49 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S
animStream->skip(2);
_field12 = animStream->readUint16LE() != 0;
_spriteListIndex = animStream->readUint16LE();
- _scrollX = animStream->readUint16LE();
+ _scrollX = animStream->readSint16LE();
_scrollY = animStream->readSint16LE();
- animStream->skip(10);
+ _scrollTicks = animStream->readUint16LE();
+ animStream->skip(8);
- animStream->read(buffer, 13);
- _interfaceFile = Common::String(buffer, 13);
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ _interfaceFile = Common::String(buffer);
for (int i = 0; i < 10; ++i) {
- animStream->read(buffer, 13);
- _spriteSetNames[i] = Common::String(buffer, 13);
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ _spriteSetNames[i] = Common::String(buffer);
}
animStream->skip(81);
- animStream->read(buffer, 13);
- _lbmFilename = Common::String(buffer, 13);
- animStream->read(buffer, 13);
- _spritesFilename = Common::String(buffer, 13);
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ _lbmFilename = Common::String(buffer);
+
+ animStream->skip(365);
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ _spritesFilename = Common::String(buffer);
+
animStream->skip(48);
- animStream->read(buffer, 13);
- _soundName = Common::String(buffer, 13);
- animStream->skip(26);
- animStream->read(buffer, 13);
- Common::String fontResource(buffer, 13);
+ animStream->read(buffer, FILENAME_SIZE);
+ buffer[FILENAME_SIZE] = '\0';
+ _soundName = Common::String(buffer);
+
+ 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(interfaceSurface, sceneSurface);
+ loadInterface(surface, depthSurface);
// Initialise the reference list
for (int i = 0; i < spriteListCount; ++i)
@@ -130,21 +146,24 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S
for (int i = 0; i < messagesCount; ++i) {
AnimMessage rec;
- animStream->read(rec.msg, 70);
- rec.pos.x = animStream->readUint16LE();
- rec.pos.y = animStream->readUint16LE();
- animStream->readUint16LE();
- rec.rgb1.r = animStream->readByte();
- rec.rgb1.g = animStream->readByte();
- rec.rgb1.b = animStream->readByte();
- rec.rgb2.r = animStream->readByte();
- rec.rgb2.g = animStream->readByte();
- rec.rgb2.b = animStream->readByte();
- rec.kernelMsgIndex = animStream->readUint16LE();
+ 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->readUint16LE();
+ animStream->skip(2);
_messages.push_back(rec);
}
@@ -162,9 +181,9 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S
rec.seqIndex = animStream->readByte();
rec.spriteSlot.spriteListIndex = animStream->readByte();
rec.spriteSlot.frameNumber = animStream->readUint16LE();
- rec.spriteSlot.xp = animStream->readUint16LE();
- rec.spriteSlot.yp = animStream->readUint16LE();
- rec.spriteSlot.depth = animStream->readByte();
+ 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);
@@ -180,7 +199,7 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S
for (int i = 0; i < miscEntriesCount; ++i) {
AnimMiscEntry rec;
rec.soundNum = animStream->readByte();
- animStream->skip(1);
+ rec.msgIndex = animStream->readSByte();
rec.numTicks = animStream->readUint16LE();
rec.posAdjust.x = animStream->readUint16LE();
rec.posAdjust.y = animStream->readUint16LE();
@@ -199,9 +218,16 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S
fontName += "*";
fontName += fontResource;
- _font = _vm->_font->getFont(fontName);
+ 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))
@@ -232,6 +258,9 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S
int idx = _frameEntries[i].spriteSlot.spriteListIndex;
_frameEntries[i].spriteSlot.spriteListIndex = _spriteListIndexes[idx];
}
+
+ if (hasScroll())
+ _nextScrollTimer = _madsVm->_currentTimer + _scrollTicks;
}
/**
@@ -258,8 +287,8 @@ void MadsAnimation::load(const Common::String &filename, int abortTimers) {
_abortTimers = abortTimers;
_abortMode = _madsVm->scene()->_abortTimersMode2;
- for (int i = 0; i < 3; ++i)
- _actionNouns[i] = _madsVm->scene()->actionNouns[i];
+ if (_madsVm->_scene)
+ _actionNouns = _madsVm->scene()->_action._action;
// Initialise kernel message list
for (uint i = 0; i < _messages.size(); ++i)
@@ -282,9 +311,24 @@ void MadsAnimation::update() {
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 (_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) {
@@ -311,25 +355,17 @@ void MadsAnimation::update() {
if (misc.soundNum)
_vm->_sound->playSound(misc.soundNum);
- bool screenChanged = false;
-
- // Handle any scrolling of the screen surface
- if ((_scrollX != 0) || (_scrollY != 0)) {
- _view->_bgSurface->scrollX(_scrollX);
- _view->_bgSurface->scrollY(_scrollY);
-
- screenChanged = true;
- }
-
// Handle any offset adjustment for sprites as of this frame
if (_view->_posAdjust.x != misc.posAdjust.x) {
- misc.posAdjust.x = _view->_posAdjust.x;
+ _view->_posAdjust.x = misc.posAdjust.x;
screenChanged = true;
}
if (_view->_posAdjust.y != misc.posAdjust.y) {
- misc.posAdjust.y = _view->_posAdjust.y;
+ _view->_posAdjust.y = misc.posAdjust.y;
screenChanged = true;
}
+
+
if (screenChanged) {
// Signal the entire screen needs refreshing
_view->_spriteSlots.fullRefresh();
@@ -408,7 +444,12 @@ void MadsAnimation::update() {
_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 * 101, 0, 0, INDEFINITE_TIMEOUT, me.msg);
+ 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;
}
}
@@ -423,8 +464,8 @@ void MadsAnimation::update() {
if (_abortMode != ABORTMODE_1) {
// Copy the noun list
- for (int i = 0; i < 3; ++i)
- _madsVm->scene()->actionNouns[i] = _actionNouns[i];
+ if (_madsVm->_scene)
+ _madsVm->scene()->_action._action = _actionNouns;
}
}
}
@@ -437,6 +478,12 @@ void MadsAnimation::setCurrentFrame(int frameNumber) {
_currentFrame = frameNumber;
_oldFrameEntry = 0;
_freeFlag = false;
+
+ _nextScrollTimer = _nextFrameTimer = _madsVm->_currentTimer;
+}
+
+int MadsAnimation::getCurrentFrame() {
+ return _currentFrame;
}
void MadsAnimation::load1(int frameNumber) {
diff --git a/engines/m4/animation.h b/engines/m4/animation.h
index 5c7227a256..a7a6b57c32 100644
--- a/engines/m4/animation.h
+++ b/engines/m4/animation.h
@@ -39,12 +39,13 @@ class SpriteSlotSubset;
class AnimMessage {
public:
- char msg[70];
+ int16 soundId;
+ char msg[64];
Common::Point pos;
RGB8 rgb1, rgb2;
- int kernelMsgIndex;
-
+ uint16 flags;
int startFrame, endFrame;
+ int kernelMsgIndex;
};
class AnimFrameEntry {
@@ -57,6 +58,7 @@ public:
class AnimMiscEntry {
public:
int soundNum;
+ int msgIndex;
int numTicks;
Common::Point posAdjust;
};
@@ -82,11 +84,13 @@ private:
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;
@@ -96,24 +100,28 @@ private:
int _unkIndex;
Common::Point _unkList[2];
uint32 _nextFrameTimer;
+ uint32 _nextScrollTimer;
int _messageCtr;
int _abortTimers;
AbortTimerMode _abortMode;
- uint16 _actionNouns[3];
+ 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 *interfaceSurface, M4Surface *sceneSurface);
+ 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; }
};
diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp
index 1f3cf278ae..23122eb960 100644
--- a/engines/m4/assets.cpp
+++ b/engines/m4/assets.cpp
@@ -98,7 +98,8 @@ long *DataAsset::getRow(int index) {
return &_data[_recSize * index];
}
-SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) :
+SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name,
+ bool asStream, int flags) :
BaseAsset(vm) {
_stream = stream;
_palInterface = NULL;
@@ -107,7 +108,7 @@ SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, i
if (_vm->isM4()) {
loadM4SpriteAsset(vm, stream, asStream);
} else {
- loadMadsSpriteAsset(vm, stream);
+ loadMadsSpriteAsset(vm, stream, flags);
}
}
@@ -119,7 +120,7 @@ SpriteAsset::SpriteAsset(MadsM4Engine *vm, const char *name): BaseAsset(vm) {
if (_vm->isM4()) {
loadM4SpriteAsset(vm, _stream, true);
} else {
- loadMadsSpriteAsset(vm, _stream);
+ loadMadsSpriteAsset(vm, _stream, 0);
}
vm->res()->toss(name);
@@ -136,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) {
@@ -200,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);
@@ -217,7 +220,12 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre
_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
@@ -234,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();
@@ -247,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;
}
@@ -320,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) {
@@ -578,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 e5beffbcae..3ae7fb2e22 100644
--- a/engines/m4/assets.h
+++ b/engines/m4/assets.h
@@ -44,6 +44,8 @@ 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;
@@ -100,13 +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; }
@@ -124,6 +141,8 @@ 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];
diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp
index 4e14afdfaf..71c70e3e1b 100644
--- a/engines/m4/console.cpp
+++ b/engines/m4/console.cpp
@@ -103,8 +103,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;
}
@@ -196,7 +196,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 11bc165811..af26a86313 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 4afa158976..b5965732e5 100644
--- a/engines/m4/font.cpp
+++ b/engines/m4/font.cpp
@@ -35,27 +35,34 @@ FontManager::~FontManager() {
_entries.clear();
}
-Font *FontManager::getFont(const Common::String &filename) {
+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 (_entries[i]->_filename.equals(filename))
+ for (uint i = 0; i < _entries.size(); ++i) {
+ if (!strcmp(_entries[i]->_filename, buffer))
return _entries[i];
}
- Font *f = new Font(_vm, filename);
+ Font *f = new Font(_vm, buffer);
_entries.push_back(f);
return f;
}
-void FontManager::setFont(const Common::String &filename) {
+void FontManager::setFont(const char *filename) {
_currentFont = getFont(filename);
}
//--------------------------------------------------------------------------
-Font::Font(MadsM4Engine *vm, const Common::String &filename) : _vm(vm), _filename(filename) {
+Font::Font(MadsM4Engine *vm, const char *filename) : _vm(vm) {
_sysFont = true;
+ strncpy(_filename, filename, 19);
+ _filename[19] = '\0';
//TODO: System font
_fontColors[0] = _vm->_palette->BLACK;
@@ -66,9 +73,9 @@ Font::Font(MadsM4Engine *vm, const Common::String &filename) : _vm(vm), _filenam
_sysFont = false;
if (_vm->isM4())
- setFontM4(filename.c_str());
+ setFontM4(filename);
else
- setFontMads(filename.c_str());
+ setFontMads(filename);
}
void Font::setFontM4(const char *filename) {
diff --git a/engines/m4/font.h b/engines/m4/font.h
index ca47848c61..19d15faa1e 100644
--- a/engines/m4/font.h
+++ b/engines/m4/font.h
@@ -59,7 +59,7 @@ namespace M4 {
class Font {
public:
- Font(MadsM4Engine *vm, const Common::String &filename);
+ Font(MadsM4Engine *vm, const char *filename);
~Font();
void setColour(uint8 colour);
@@ -73,7 +73,7 @@ public:
return write(surface, text, x, y, width, spaceWidth, _fontColors);
}
public:
- const Common::String _filename;
+ char _filename[20];
private:
void setFontM4(const char *filename);
void setFontMads(const char *filename);
@@ -108,8 +108,8 @@ public:
FontManager(MadsM4Engine *vm): _vm(vm) { _currentFont = NULL; }
~FontManager();
- Font *getFont(const Common::String &filename);
- void setFont(const Common::String &filename);
+ Font *getFont(const char *filename);
+ void setFont(const char *filename);
Font *current() {
assert(_currentFont);
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 de6e716ece..3fc31b4ec2 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 8624f18da1..423dda5e7e 100644
--- a/engines/m4/graphics.cpp
+++ b/engines/m4/graphics.cpp
@@ -65,6 +65,15 @@ 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)
@@ -74,6 +83,8 @@ M4Surface::~M4Surface() {
_madsVm->_palette->deleteRange(_rgbList);
delete _rgbList;
}
+ if (_ownsData)
+ free();
}
void M4Surface::loadCodesM4(Common::SeekableReadStream *source) {
@@ -331,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);
}
@@ -389,43 +410,40 @@ void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int dest
* 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) {
- /* TODO: This isn't a straight re-implementation of the original draw routine. Double check in future
- * whether this implementation provides equivalent functionality
- */
- Common::Rect copyRect(0, 0, src->width(), src->height());
+void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth,
+ M4Surface *depthsSurface, int scale, int transparentColour) {
- 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;
+ 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;
+ }
- // Copy the specified area
+ if (!copyRect.isValidRect())
+ return;
- byte *data = src->getBasePtr();
- byte *srcPtr = data + (src->width() * copyRect.top + copyRect.left);
- byte *depthsData = depthsSurface->getBasePtr();
- byte *depthsPtr = depthsData + (src->width() * copyRect.top + copyRect.left);
- byte *destPtr = (byte *)pixels + (destY * width()) + destX;
+ 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;
- if (scale == 100) {
// 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 ((depthsPtr[xCtr] > depth) && (srcPtr[xCtr] != transparentColour))
+ if ((depth <= (depthsPtr[xCtr] & 0x7f)) && (srcPtr[xCtr] != transparentColour))
destPtr[xCtr] = srcPtr[xCtr];
}
@@ -433,31 +451,127 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surf
depthsPtr += depthsSurface->width();
destPtr += width();
}
- } else {
- // Scaled variation
- for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) {
- int currX = -1;
- // Loop through the source pixels
- for (int xCtr = 0, xTotal = 0; xCtr < copyRect.width(); ++xCtr, xTotal += (100 - scale)) {
- int srcX = xTotal / 100;
+ src->freeData();
+ depthsSurface->freeData();
+ return;
+ }
- if (srcX != currX) {
- currX = srcX;
+ // 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 ((depthsPtr[currX] > depth) && (srcPtr[xCtr] != transparentColour))
- destPtr[currX] = srcPtr[xCtr];
- }
- }
+ if (distIndex < frameWidth)
+ ++distXCount;
- srcPtr += src->width();
- depthsPtr += depthsSurface->width();
- destPtr += width();
+ 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) {
@@ -471,8 +585,6 @@ 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;
@@ -752,7 +864,7 @@ void M4Surface::scrollX(int xAmount) {
return;
byte buffer[80];
- int direction = (xAmount > 0) ? 1 : -1;
+ int direction = (xAmount > 0) ? -1 : 1;
int xSize = ABS(xAmount);
assert(xSize <= 80);
@@ -817,15 +929,32 @@ void M4Surface::translate(RGBList *list, bool isTransparent) {
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 8c4b9ac072..ecb5048b26 100644
--- a/engines/m4/graphics.h
+++ b/engines/m4/graphics.h
@@ -40,6 +40,7 @@ namespace M4 {
#define MADS_SCREEN_HEIGHT 200
#define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2)
+#define TRANSPARENT_COLOUR_INDEX 0xFF
struct BGR8 {
uint8 b, g, r;
@@ -74,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
@@ -96,6 +98,7 @@ private:
byte _color;
bool _isScreen;
RGBList *_rgbList;
+ bool _ownsData;
void rexLoadBackground(Common::SeekableReadStream *source, RGBList **palData = NULL);
void madsLoadBackground(int roomNumber, RGBList **palData = NULL);
@@ -105,12 +108,24 @@ public:
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
@@ -142,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;
@@ -154,12 +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 transparentColour = -1);
- void copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surface *depthSurface, int scale,
- int transparentColour = -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) {
@@ -188,6 +204,7 @@ public:
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 a5db6660d8..a999a6bd5a 100644
--- a/engines/m4/m4.cpp
+++ b/engines/m4/m4.cpp
@@ -147,6 +147,8 @@ MadsM4Engine::~MadsM4Engine() {
delete _random;
delete _palette;
delete _globals;
+ delete _sound;
+ delete _driver;
delete _resourceManager;
}
@@ -154,14 +156,14 @@ 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);
@@ -512,7 +514,6 @@ Common::Error MadsEngine::run() {
// Set up needed common functionality
MadsM4Engine::run();
- _scene = new MadsScene(this);
_palette->setMadsSystemPalette();
_mouse->init("cursor.ss", NULL);
@@ -536,16 +537,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();
@@ -564,15 +569,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 9937107668..3174c886d5 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:
@@ -211,6 +214,7 @@ private:
public:
MadsConversation _converse;
uint32 _currentTimer;
+ MadsPlayer _player;
public:
MadsEngine(OSystem *syst, const M4GameDescription *gameDesc);
virtual ~MadsEngine();
@@ -219,6 +223,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 e1dbbaf106..ca53bdca75 100644
--- a/engines/m4/mads_anim.cpp
+++ b/engines/m4/mads_anim.cpp
@@ -446,7 +446,7 @@ AnimviewView::AnimviewView(MadsM4Engine *vm):
MadsView::_bgSurface = &_backgroundSurface;
MadsView::_depthSurface = &_codeSurface;
- MadsView::_yOffset = MADS_Y_OFFSET;
+ MadsView::setViewport(Common::Rect(0, MADS_Y_OFFSET, MADS_SURFACE_WIDTH, MADS_Y_OFFSET + MADS_SURFACE_HEIGHT));
_screenType = VIEWID_ANIMVIEW;
_screenFlags.layer = LAYER_BACKGROUND;
@@ -458,11 +458,19 @@ AnimviewView::AnimviewView(MadsM4Engine *vm):
_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();
_backgroundSurface.clear();
@@ -510,7 +518,9 @@ bool AnimviewView::onEvent(M4EventType eventType, int32 param, int x, int y, boo
}
void AnimviewView::updateState() {
- if (!_script)
+ MadsView::update();
+
+ if (!_script || _scriptDone)
return;
if (!_activeAnimation) {
@@ -524,19 +534,35 @@ void AnimviewView::updateState() {
delete _activeAnimation;
_activeAnimation = NULL;
- if (_script->eos() || _script->err()) {
+ // Clear up current background and sprites
+ _backgroundSurface.reset();
+ clearLists();
+
+ // Reset flags
+ _startFrame = -1;
+
+ readNextCommand();
+
+ // Check if script is finished
+ if (_scriptDone) {
scriptDone();
return;
}
-
- readNextCommand();
}
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
@@ -564,15 +590,24 @@ void AnimviewView::readNextCommand() {
break;
}
+ 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");
+ uint16 flags = 0;
+ if (_bgLoadFlag)
+ flags |= 0x100;
+
_activeAnimation = new MadsAnimation(_vm, this);
- _activeAnimation->load(_currentLine, 0);
+ _activeAnimation->initialise(_currentLine, flags, &_backgroundSurface, &_codeSurface);
- _backgroundSurface.loadBackground(_activeAnimation->roomNumber());
- _codeSurface.setSize(_backgroundSurface.width(), _backgroundSurface.height());
- _codeSurface.fillRect(_codeSurface.bounds(), 0xff);
+ if (_startFrame != -1)
+ _activeAnimation->setCurrentFrame(_startFrame);
_spriteSlots.fullRefresh();
/*
@@ -627,6 +662,7 @@ return;
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.
@@ -670,18 +706,39 @@ 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 {
+ break;
+
+ case 'R':
+ param = param + 2;
+ //printf("R:%s ", param);
+ break;
+
+ case 'W':
+ //printf("W ");
+ break;
+
+ case 'X':
+ //printf("X ");
+ break;
+
+ default:
error("Unknown response command: '%s'", commandStr);
}
}
diff --git a/engines/m4/mads_anim.h b/engines/m4/mads_anim.h
index 8c4a5e6fb7..b33ea24071 100644
--- a/engines/m4/mads_anim.h
+++ b/engines/m4/mads_anim.h
@@ -81,6 +81,7 @@ class AnimviewView : public View, MadsView {
private:
char _resourceName[80];
Common::SeekableReadStream *_script;
+ bool _scriptDone;
uint32 _previousUpdate;
char _currentLine[80];
M4Surface _backgroundSurface;
@@ -90,6 +91,8 @@ private:
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 9cb053a876..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,7 +162,7 @@ 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;
@@ -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,30 +189,30 @@ 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) {
+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,
+ 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) {
+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,
+ 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) {
+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,
+ return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0,
true, 100, depth - 1, -1, ANIMTYPE_CYCLED, 0, 0);
}
@@ -146,6 +258,59 @@ 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);
+}
+
/*--------------------------------------------------------------------------*/
@@ -171,7 +336,9 @@ void MadsSceneLogic::setupScene() {
// sub_1e754(animName, 3);
if ((_sceneNumber >= 101) && (_sceneNumber <= 112))
- getSceneSpriteSet();
+ getPlayerSpritesPrefix();
+ else
+ getPlayerSpritesPrefix2();
getAnimName();
}
@@ -187,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;
@@ -208,18 +373,18 @@ void MadsSceneLogic::enterScene() {
if (_madsVm->globals()->previousScene != -1)
_madsVm->globals()->_globals[10] = 0;
if (_madsVm->globals()->previousScene != -2) {
- _madsVm->scene()->getSceneResources().playerPos = Common::Point(100, 152);
+ _madsVm->_player._playerPos = Common::Point(100, 152);
}
if ((_madsVm->globals()->previousScene == 112) ||
((_madsVm->globals()->previousScene != -2) && (_spriteIndexes[29] != 0))) {
// Returning from probe cutscene?
_spriteIndexes[29] = -1;
- _madsVm->scene()->getSceneResources().playerPos = Common::Point(161, 123);
- _madsVm->scene()->getSceneResources().playerDir = 9;
+ _madsVm->_player._playerPos = Common::Point(161, 123);
+ _madsVm->_player._direction = 9;
// TODO: Extra flags setting
- _spriteIndexes[25] = startCycledSpriteSequence(_spriteIndexes[10], 0, 3, 0, 0, 0);
+ _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,
@@ -228,36 +393,99 @@ void MadsSceneLogic::enterScene() {
//if (_madsVm->globals()->previousScene == 112)
// room101Check();
} else {
- _spriteIndexes[26] = startCycledSpriteSequence(_spriteIndexes[11], 0, 6, 0, 0, 0);
+ _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, 0x47);
+ _madsVm->scene()->loadAnimation(animName, 71);
- _madsVm->scene()->getSceneResources().playerPos = Common::Point(68, 140);
- _madsVm->scene()->getSceneResources().playerDir = 4;
- // TODO: Flags setting
+ _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::doAction() {
-
+void MadsSceneLogic::doPreactions() {
+ warning("Still to do preactions logic");
}
-void MadsSceneLogic::sceneStep() {
- // FIXME: Temporary code to display a message on-screen
- static bool tempBool = false;
- if (!tempBool) {
- tempBool = true;
+void MadsSceneLogic::doAction() {
+ warning("Still to do actions logic");
+}
- _madsVm->scene()->_kernelMessages.add(Common::Point(63, 100), 0x1110, 0, 0, 240,
- _madsVm->globals()->getQuote(49));
+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 8c3f41d08b..ec6eff368b 100644
--- a/engines/m4/mads_logic.h
+++ b/engines/m4/mads_logic.h
@@ -37,11 +37,13 @@ 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];
@@ -50,13 +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 sceneStep();
+ void doSceneStep();
+};
+
+class MadsGameLogic {
+public:
+ static void initialiseGlobals();
};
}
diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp
index 94894e78be..810acb04fb 100644
--- a/engines/m4/mads_menus.cpp
+++ b/engines/m4/mads_menus.cpp
@@ -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 a65224c722..d44fa2a753 100644
--- a/engines/m4/mads_scene.cpp
+++ b/engines/m4/mads_scene.cpp
@@ -48,6 +48,17 @@ 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;
@@ -55,8 +66,8 @@ MadsScene::MadsScene(MadsEngine *vm): _sceneResources(), Scene(vm, &_sceneResour
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() {
@@ -69,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();
@@ -117,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();
@@ -150,24 +195,21 @@ 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) {
@@ -196,57 +238,43 @@ void MadsScene::loadSceneCodes(int sceneNumber, int index) {
}
}
-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;
-
- sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(verbId), currentHotSpot->getVocab());
+ _action._selectedRow = -1;
+ _action._actionMode = ACTMODE_NONE;
+ _action._actionMode2 = ACTMODE2_4;
+ _action._hotspotId = currentHotSpot->getIndex();
- 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
@@ -263,7 +291,7 @@ void MadsScene::setAction(int action, int objectId) {
_currentAction = action;
}
*/
- setStatusText(statusText);
+// setStatusText(statusText);
}
/**
@@ -282,66 +310,162 @@ void MadsScene::update() {
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->current()->setColours(_vm->_palette->BLACK, _vm->_palette->WHITE, _vm->_palette->BLACK);
- else
- _vm->_font->current()->setColours(_vm->_palette->WHITE, _vm->_palette->BLACK, _vm->_palette->BLACK);
-
- _vm->_font->setFont(FONT_MAIN_MADS);
- _vm->_font->current()->writeString(this, sStatusText, (width() - _vm->_font->current()->getWidth(sStatusText)) / 2, 142, 0);
- }
}
void MadsScene::updateState() {
- _sceneLogic.sceneStep();
- _sequenceList.tick();
+ if (!_abortTimers && !_madsVm->_player._unk3) {
+ if (_dynamicHotspots._changed)
+ _dynamicHotspots.refresh();
+
+// int v = (_madsVm->_player._stepEnabled && !_action._startWalkFlag && !_abortTimers2) ? 1 : 0;
+// _screenObjects.check(v, false);
+ }
+
+ // 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();
+
+ 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();
+ }
+
+ if (_madsVm->_player._visible) {
+ _madsVm->_player._forceRefresh = true;
+ _madsVm->_player.update();
}
- error("Couldn't find player sprites");
+ 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 {
@@ -442,188 +566,29 @@ 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 v0) {
+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(), 0);
+ anim->load(animName.c_str(), abortTimers);
_activeAnimation = anim;
}
-/*--------------------------------------------------------------------------*/
-
-MadsAction::MadsAction() {
- clear();
-}
+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;
-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;
+ return (*p & 0x80) != 0;
}
-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);
+bool MadsScene::getDepthHighBits(const Common::Point &pt) {
+ if (_sceneResources._depthStyle == 2)
+ return 0;
- 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);
- } 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);
-
- _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 ((_currentHotspot >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_flags1 == 2)) {
- flag = true;
-
- strcat(_statusText, englishMADSArticleList[_articleNumber]);
- strcat(_statusText, " ");
- }
-
- 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);
- }
- }
-
- 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();
- }
- }
- }
-
- if ((_currentHotspot >= 0) && (_articleNumber > 0) && !flag) {
- if (_articleNumber == -1) {
- if (_word_86F3A >= 0) {
- int articleNum = 0;
-
- 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 {
-
- }
- }
-
- } 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);
- }
-
- strcat(_statusText, " ");
- }
-
- // Append object description if necessary
- if (_word_86F3A >= 0)
- appendVocab(_objectDescId);
-
- // Remove any trailing space character
- int statusLen = strlen(_statusText);
- if ((statusLen > 0) && (_statusText[statusLen - 1] == ' '))
- _statusText[statusLen - 1] = '\0';
- }
-
- _word_83334 = -1;
+ const byte *p = _depthSurface->getBasePtr(pt.x, pt.y);
+ return (*p & 0x70) >> 4;
}
/*--------------------------------------------------------------------------*/
@@ -637,7 +602,7 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su
if (sceneNumber > 0) {
sceneName = MADSResourceManager::getResourceName(RESPREFIX_RM, sceneNumber, ".DAT");
} else {
- strcat(buffer1, "*");
+ strcpy(buffer1, "*");
strcat(buffer1, resName);
sceneName = buffer1; // TODO: Check whether this needs to be converted to 'HAG form'
}
@@ -649,53 +614,75 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su
// Basic scene info
Common::SeekableReadStream *stream = sceneInfo.getItemStream(0);
- int resSceneId = stream->readUint16LE();
- assert(resSceneId == sceneNumber);
- artFileNum = stream->readUint16LE();
- drawStyle = stream->readUint16LE();
- width = stream->readUint16LE();
- height = stream->readUint16LE();
- assert((width == 320) && (height == 156));
+ if (_vm->getGameType() == GType_RexNebular) {
+ int resSceneId = stream->readUint16LE();
+ assert(resSceneId == sceneNumber);
+ } else {
+ char roomFilename[10];
+ char roomFilenameExpected[10];
+ sprintf(roomFilenameExpected, "*RM%d", sceneNumber);
+
+ stream->read(roomFilename, 6);
+ roomFilename[6] = 0;
+ assert(!strcmp(roomFilename, roomFilenameExpected));
+ }
+
+ // TODO: The following is wrong for Phantom/Dragon
+ _artFileNum = stream->readUint16LE();
+ _depthStyle = stream->readUint16LE();
+ _width = stream->readUint16LE();
+ _height = stream->readUint16LE();
stream->skip(24);
- int objectCount = stream->readUint16LE();
-
- stream->skip(40);
+ 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 < objectCount; ++i) {
- MadsObject rec;
+ for (int i = 0; i < nodeCount; ++i) {
+ SceneNode rec;
rec.load(stream);
- objects.push_back(rec);
+ _nodes.push_back(rec);
}
- for (int i = 0; i < 20 - objectCount; ++i)
+ for (int i = 0; i < 20 - nodeCount; ++i)
stream->skip(48);
+ // 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);
+ _setNames.push_back(s);
}
-
+
+ delete stream;
+
// Initialise a copy of the surfaces if they weren't provided
bool dsFlag = false, ssFlag = false;
- int gfxSize = width * height;
if (!surface) {
- surface = new M4Surface(width, height);
+ surface = new M4Surface(_width, _height);
ssFlag = true;
- }
- int walkSize = gfxSize;
- if (drawStyle == 2) {
- width >>= 2;
- walkSize = width * height;
- }
+ } else if ((_width != surface->width()) || (_height != surface->height()))
+ surface->setSize(_width, _height);
+
if (!depthSurface) {
- depthSurface = new M4Surface(width, height);
+ 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) {
@@ -708,19 +695,32 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su
byte *destP = depthSurface->getBasePtr(0, 0);
const byte *srcP = walkData;
byte runLength;
+
+ // Run length encoded depth data
while ((runLength = *srcP++) != 0) {
- Common::set_to(destP, destP + runLength, *srcP++);
- destP += runLength;
+ 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;
+ }
}
- delete walkData;
+ free(walkData);
delete stream;
}
_vm->_resourceManager->toss(sceneName);
// Load the surface artwork
- surface->loadBackground(sceneNumber);
+ surface->loadBackground(_artFileNum);
// Final cleanup
if (ssFlag)
@@ -729,6 +729,84 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su
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);
+
+ 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;
+ }
+
+ while (totalCtr >= xDiff) {
+ totalCtr -= xDiff;
+
+ if ((*srcP & 0x80) == 0)
+ flag = false;
+ else if (!flag) {
+ flag = true;
+ result -= 0x4000;
+ if (result == 0)
+ break;
+ }
+
+ srcP += yDirection;
+ }
+ if (result == 0)
+ break;
+ }
+
+ return result;
+}
/*--------------------------------------------------------------------------*/
@@ -915,7 +993,7 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
// Display object sprite. Note that the frame number isn't used directly, because it would result
// in too fast an animation
M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED);
- spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, 0);
+ 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
@@ -943,7 +1021,7 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) {
}
bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) {
- MadsAction &act = _madsVm->scene()->getAction();
+ MadsAction &act = _madsVm->scene()->_action;
// If the mouse isn't being held down, then reset the repeated scroll timer
if (eventType != MEVENT_LEFT_HOLD)
@@ -990,7 +1068,7 @@ bool MadsInterfaceView::onEvent(M4EventType eventType, int32 param1, int x, int
act._flags1 = obj->vocabList[1].flags1;
act._flags2 = obj->vocabList[1].flags2;
- act._currentHotspot = _selectedObject;
+ act._action.verbId = _selectedObject;
act._articleNumber = act._flags2;
}
}
@@ -1043,8 +1121,13 @@ bool MadsInterfaceView::handleCheatKey(int32 keycode) {
// TODO: Move player to current destination
return true;
- case Common::KEYCODE_t | (Common::KEYCODE_LALT):
- case Common::KEYCODE_t | (Common::KEYCODE_RALT):
+ 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);
@@ -1111,9 +1194,9 @@ bool MadsInterfaceView::handleKeypress(int32 keycode) {
warning("TODO: Activate sound");
break;
- case Common::KEYCODE_u:
- // Rotate player
- warning("TODO: Rotate player");
+ 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: {
diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h
index 0269de75c8..7723058cc7 100644
--- a/engines/m4/mads_scene.h
+++ b/engines/m4/mads_scene.h
@@ -35,79 +35,79 @@ namespace M4 {
#define INTERFACE_HEIGHT 106
class MadsInterfaceView;
-class MadsSceneResources: public SceneResources {
+#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:
- int sceneId;
- int artFileNum;
- int drawStyle;
- int width;
- int height;
- Common::Array<MadsObject> objects;
- Common::Array<Common::String> setNames;
-
- Common::Point playerPos;
- int playerDir;
-
- MadsSceneResources() { playerDir = 0; }
- ~MadsSceneResources() {}
- void load(int sceneId, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface);
-};
+ Common::Point pt;
+ int indexes[MAX_ROUTE_NODES];
-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};
+ bool active;
-class MadsAction {
-private:
- char _statusText[100];
+ SceneNode() {
+ active = false;
+ }
- 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;
+ void load(Common::SeekableReadStream *stream);
+};
-public:
- MadsAction();
+typedef Common::Array<SceneNode> SceneNodeList;
- void clear();
- void set();
- const char *statusText() const { return _statusText; }
+class MadsSceneResources: public SceneResources {
+private:
+ int getRouteFlags(const Common::Point &src, const Common::Point &dest, M4Surface *depthSurface);
+public:
+ 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);
};
class MadsScene : public Scene, public MadsView {
private:
MadsEngine *_vm;
MadsSceneResources _sceneResources;
- MadsAction _action;
Animation *_activeAnimation;
MadsSceneLogic _sceneLogic;
SpriteAsset *_playerSprites;
+ 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();
@@ -117,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);
@@ -126,14 +126,15 @@ 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 v0);
+ 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
diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp
index c7b4f76a00..3e5f0c2ac9 100644
--- a/engines/m4/mads_views.cpp
+++ b/engines/m4/mads_views.cpp
@@ -37,6 +37,307 @@
namespace M4 {
+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);
@@ -86,10 +387,16 @@ 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);
@@ -99,6 +406,12 @@ int MadsSpriteSlots::addSprites(const char *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;
@@ -136,17 +449,19 @@ typedef Common::List<DepthEntry> DepthList;
void MadsSpriteSlots::drawBackground() {
// Draw all active sprites onto the background surface
for (int i = 0; i < startIndex; ++i) {
- if (_entries[i].spriteType >= 0) {
+ MadsSpriteSlot &slot = _entries[i];
+
+ if (slot.spriteType >= 0) {
_owner._dirtyAreas[i].active = false;
} else {
_owner._dirtyAreas[i].textActive = true;
- _owner._dirtyAreas.setSpriteSlot(i, _entries[i]);
+ _owner._dirtyAreas.setSpriteSlot(i, slot);
- if (_entries[i].spriteType == BACKGROUND_SPRITE) {
- SpriteAsset &spriteSet = getSprite(_entries[i].spriteListIndex);
- M4Sprite *frame = spriteSet.getFrame((_entries[i].frameNumber & 0x7fff) - 1);
- int xp = _entries[i].xp;
- int yp = _entries[i].yp;
+ 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
@@ -154,12 +469,13 @@ void MadsSpriteSlots::drawBackground() {
yp -= frame->height() / 2;
}
- if (_entries[i].depth <= 1) {
- // No depth, so simply copy the frame onto the background
- frame->copyTo(_owner._bgSurface, xp, yp, 0);
+ if (slot.depth > 1) {
+ // Draw the frame with depth processing
+ _owner._bgSurface->copyFrom(frame, xp, yp, slot.depth, _owner._depthSurface, 100,
+ frame->getTransparencyIndex());
} else {
- // Depth was specified, so draw frame using scene's depth information
- frame->copyTo(_owner._bgSurface, xp, yp, _entries[i].depth, _owner._depthSurface, 100, 0);
+ // No depth, so simply draw the image
+ frame->copyTo(_owner._bgSurface, xp, yp, frame->getTransparencyIndex());
}
}
}
@@ -170,13 +486,13 @@ void MadsSpriteSlots::drawBackground() {
_owner._dirtyAreas[i].active = false;
}
-void MadsSpriteSlots::drawForeground(View *view, int yOffset) {
+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].spriteType >= 0) {
- DepthEntry rec(_entries[i].depth, i);
+ if (_entries[i].spriteType >= SPRITE_ZERO) {
+ DepthEntry rec(16 - _entries[i].depth, i);
depthList.push_back(rec);
}
}
@@ -192,14 +508,23 @@ void MadsSpriteSlots::drawForeground(View *view, int yOffset) {
assert(slot.spriteListIndex < (int)_sprites.size());
SpriteAsset &spriteSet = *_sprites[slot.spriteListIndex];
- if (slot.scale < 100) {
+ // Get the sprite frame
+ int frameNumber = slot.frameNumber & 0x7fff;
+ bool flipped = (slot.frameNumber & 0x8000) != 0;
+ M4Sprite *sprite = spriteSet.getFrame(frameNumber - 1);
+
+ 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 & 0x7fff) - 1);
- spr->copyTo(view, slot.xp, slot.yp + yOffset, slot.depth, _owner._depthSurface, slot.scale, 0);
+ 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 - _owner._posAdjust.x;
@@ -211,12 +536,16 @@ void MadsSpriteSlots::drawForeground(View *view, int yOffset) {
if (slot.depth > 1) {
// Draw the frame with depth processing
- spr->copyTo(view, xp, yp + yOffset, slot.depth, _owner._depthSurface, 100, 0);
+ viewport->copyFrom(spr, xp, yp, slot.depth, _owner._depthSurface, 100, sprite->getTransparencyIndex());
} else {
// No depth, so simply draw the image
- spr->copyTo(view, xp, yp + yOffset, 0);
+ spr->copyTo(viewport, xp, yp, sprite->getTransparencyIndex());
}
}
+
+ // Free sprite if it was a flipped one
+ if (flipped)
+ delete spr;
}
}
@@ -270,6 +599,7 @@ 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);
}
}
@@ -307,7 +637,7 @@ int MadsTextDisplay::add(int xp, int yp, uint fontColour, int charSpacing, const
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)
+ if ((_entries[idx].expire >= 0) || !_entries[idx].active)
_owner._dirtyAreas[dirtyIdx].active = false;
else {
_owner._dirtyAreas[dirtyIdx].textActive = true;
@@ -326,23 +656,15 @@ void MadsTextDisplay::setDirtyAreas2() {
}
}
-void MadsTextDisplay::draw(View *view, int yOffset) {
+void MadsTextDisplay::draw(M4Surface *view) {
for (uint idx = 0; idx < _entries.size(); ++idx) {
if (_entries[idx].active && (_entries[idx].expire >= 0)) {
_entries[idx].font->setColours(_entries[idx].colour1, _entries[idx].colour2, 0);
_entries[idx].font->writeString(view, _entries[idx].msg,
- _entries[idx].bounds.left, _entries[idx].bounds.top + yOffset, _entries[idx].bounds.width(),
+ _entries[idx].bounds.left, _entries[idx].bounds.top, _entries[idx].bounds.width(),
_entries[idx].spacing);
}
}
-
- // Clear up any now text display entries that are to be expired
- for (uint idx = 0; idx < _entries.size(); ++idx) {
- if (_entries[idx].expire < 0) {
- _entries[idx].active = false;
- _entries[idx].expire = 0;
- }
- }
}
/**
@@ -403,17 +725,17 @@ int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 f
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_OWNER_TIMEOUT)
- 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 abortTimers, uint32 timeout) {
const char *quoteStr = _madsVm->globals()->getQuote(quoteId);
- return add(Common::Point(0, 0), 0x1110, KMSG_OWNER_TIMEOUT | KMSG_CENTER_ALIGN, abortTimers, timeout, quoteStr);
+ return add(Common::Point(0, 0), 0x1110, KMSG_PLAYER_TIMEOUT | KMSG_CENTER_ALIGN, abortTimers, timeout, quoteStr);
}
void MadsKernelMessageList::scrollMessage(int msgIndex, int numTicks, bool quoted) {
@@ -429,8 +751,8 @@ void MadsKernelMessageList::scrollMessage(int msgIndex, int numTicks, bool quote
_entries[msgIndex].asciiChar = *msgP;
_entries[msgIndex].asciiChar2 = *(msgP + 1);
- if (_entries[msgIndex].flags & KMSG_OWNER_TIMEOUT)
- _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;
}
@@ -503,7 +825,7 @@ void MadsKernelMessageList::processText(int msgIndex) {
if (_owner._abortTimersMode != ABORTMODE_1) {
for (int i = 0; i < 3; ++i)
- _madsVm->scene()->actionNouns[i] = msg.actionNouns[i];
+ _madsVm->globals()->actionNouns[i] = msg.actionNouns[i];
}
}
}
@@ -524,7 +846,7 @@ void MadsKernelMessageList::processText(int msgIndex) {
}
}
- if (msg.flags & KMSG_OWNER_TIMEOUT) {
+ if (msg.flags & KMSG_PLAYER_TIMEOUT) {
if (word_8469E != 0) {
// TODO: Figure out various flags
} else {
@@ -597,6 +919,18 @@ void MadsKernelMessageList::processText(int msgIndex) {
//--------------------------------------------------------------------------
+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
*/
@@ -649,6 +983,29 @@ 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) {
@@ -657,7 +1014,7 @@ MadsDynamicHotspots::MadsDynamicHotspots(MadsView &owner): _owner(owner) {
rec.active = false;
_entries.push_back(rec);
}
- _flag = true;
+ _changed = true;
_count = 0;
}
@@ -681,7 +1038,7 @@ int MadsDynamicHotspots::add(int descId, int field14, int seqIndex, const Common
_entries[idx].field_17 = 0;
++_count;
- _flag = true;
+ _changed = true;
if (seqIndex >= 0)
_owner._sequenceList[seqIndex].dynamicHotspotIndex = idx;
@@ -713,7 +1070,7 @@ void MadsDynamicHotspots::remove(int index) {
_entries[index].active = false;
--_count;
- _flag = true;
+ _changed = true;
}
}
@@ -722,7 +1079,7 @@ void MadsDynamicHotspots::reset() {
_entries[i].active = false;
_count = 0;
- _flag = false;
+ _changed = false;
}
/*--------------------------------------------------------------------------*/
@@ -732,9 +1089,12 @@ void MadsDirtyArea::setArea(int width, int height, int maxWidth, int maxHeight)
--bounds.left;
++width;
}
- int right = 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)
@@ -746,6 +1106,8 @@ void MadsDirtyArea::setArea(int width, int height, int maxWidth, int maxHeight)
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;
@@ -816,6 +1178,7 @@ void MadsDirtyAreas::setTextDisplay(int dirtyIdx, const MadsTextDisplayEntry &te
* @param count Number of entries to process
*/
void MadsDirtyAreas::merge(int startIndex, int count) {
+return;//***DEBUG***
if (startIndex >= count)
return;
@@ -855,13 +1218,23 @@ void MadsDirtyAreas::mergeAreas(int idx1, int idx2) {
da1.textActive = true;
}
-void MadsDirtyAreas::copy(M4Surface *dest, M4Surface *src, int yOffset) {
+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, _entries[i].bounds, _entries[i].bounds.left, _entries[i].bounds.top + yOffset);
+ 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;
+}
+
/*--------------------------------------------------------------------------*/
MadsSequenceList::MadsSequenceList(MadsView &owner): _owner(owner) {
@@ -892,7 +1265,7 @@ 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 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) {
@@ -913,7 +1286,7 @@ int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, int trigg
// Set the list entry fields
_entries[seqIndex].active = true;
_entries[seqIndex].spriteListIndex = spriteListIndex;
- _entries[seqIndex].field_2 = v0;
+ _entries[seqIndex].flipped = flipped;
_entries[seqIndex].frameIndex = frameIndex;
_entries[seqIndex].frameStart = frameStart;
_entries[seqIndex].numSprites = numSprites;
@@ -937,7 +1310,7 @@ int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, int trigg
_entries[seqIndex].abortMode = _owner._abortTimersMode2;
for (int i = 0; i < 3; ++i)
- _entries[seqIndex].actionNouns[i] = _madsVm->scene()->actionNouns[i];
+ _entries[seqIndex].actionNouns[i] = _madsVm->globals()->actionNouns[i];
return seqIndex;
}
@@ -959,7 +1332,7 @@ void MadsSequenceList::setSpriteSlot(int seqIndex, MadsSpriteSlot &spriteSlot) {
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;
@@ -1011,7 +1384,7 @@ bool MadsSequenceList::loadSprites(int seqIndex) {
dynHotspot.bounds.top = MAX(y2 - height, 0);
dynHotspot.bounds.bottom = MIN(y2, 155) - dynHotspot.bounds.top;
- _owner._dynamicHotspots._flag = true;
+ _owner._dynamicHotspots._changed = true;
}
}
@@ -1160,6 +1533,13 @@ void MadsSequenceList::scan() {
}
}
+/**
+ * Sets the depth of the specified entry in the sequence list
+ */
+void MadsSequenceList::setDepth(int seqIndex, int depth) {
+ _entries[seqIndex].depth = depth;
+}
+
//--------------------------------------------------------------------------
Animation::Animation(MadsM4Engine *vm): _vm(vm) {
@@ -1171,28 +1551,33 @@ Animation::~Animation() {
//--------------------------------------------------------------------------
MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this),
- _kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this) {
+ _kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this),
+ _screenObjects(*this), _action(*this) {
_textSpacing = -1;
- _ticksAmount = 3;
_newTimeout = 0;
_abortTimers = 0;
_abortTimers2 = 0;
_abortTimersMode = ABORTMODE_0;
_abortTimersMode2 = ABORTMODE_0;
- _yOffset = 0;
_depthSurface = NULL;
_bgSurface = NULL;
+ _viewport = NULL;
_sceneAnimation = new MadsAnimation(_vm, this);
}
MadsView::~MadsView() {
delete _sceneAnimation;
+ delete _viewport;
}
void MadsView::refresh() {
+ if (!_viewport)
+ setViewport(_view->bounds());
+
// Draw any sprites
+ _dirtyAreas.clear();
_spriteSlots.drawBackground();
// Process dirty areas
@@ -1202,7 +1587,7 @@ void MadsView::refresh() {
_dirtyAreas.merge(1, DIRTY_AREAS_SIZE);
// Copy dirty areas to the main display surface
- _dirtyAreas.copy(_view, _bgSurface, _yOffset);
+ _dirtyAreas.copy(_viewport, _bgSurface, _posAdjust);
// Handle dirty areas for foreground objects
_spriteSlots.setDirtyAreas();
@@ -1210,10 +1595,10 @@ void MadsView::refresh() {
_dirtyAreas.merge(1, DIRTY_AREAS_SIZE);
// Draw foreground sprites
- _spriteSlots.drawForeground(_view, _yOffset);
+ _spriteSlots.drawForeground(_viewport);
// Draw text elements onto the view
- _textDisplay.draw(_view, _yOffset);
+ _textDisplay.draw(_viewport);
// Remove any sprite slots that are no longer needed
_spriteSlots.cleanUp();
@@ -1222,4 +1607,21 @@ void MadsView::refresh() {
_textDisplay.cleanUp();
}
+void MadsView::update() {
+ _sequenceList.tick();
+ _kernelMessages.update();
+}
+
+void MadsView::clearLists() {
+ _textDisplay.clear();
+ _kernelMessages.clear();
+ _spriteSlots.clear();
+}
+
+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 29adb7048a..c93d0beda3 100644
--- a/engines/m4/mads_views.h
+++ b/engines/m4/mads_views.h
@@ -36,6 +36,69 @@ namespace M4 {
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 {
@@ -92,13 +155,14 @@ public:
}
int getIndex();
- int addSprites(const char *resName);
+ 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 drawBackground();
- void drawForeground(View *view, int yOffset);
+ void drawForeground(M4Surface *viewport);
void setDirtyAreas();
void fullRefresh();
void cleanUp();
@@ -139,7 +203,7 @@ public:
int add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font);
void clear();
- void draw(View *view, int yOffset);
+ void draw(M4Surface *view);
void setDirtyAreas();
void setDirtyAreas2();
void cleanUp();
@@ -148,7 +212,7 @@ public:
#define TIMED_TEXT_SIZE 10
#define INDEFINITE_TIMEOUT 9999999
-enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_OWNER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10,
+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 MadsKernelMessageEntry {
@@ -170,6 +234,10 @@ public:
AbortTimerMode abortMode;
uint16 actionNouns[3];
char msg[100];
+
+ MadsKernelMessageEntry() {
+ flags = 0;
+ }
};
class MadsKernelMessageList {
@@ -206,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];
@@ -221,6 +299,7 @@ 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 {
@@ -246,7 +325,7 @@ private:
Common::Array<DynamicHotspot> _entries;
int _count;
public:
- bool _flag;
+ bool _changed;
public:
MadsDynamicHotspots(MadsView &owner);
@@ -256,6 +335,9 @@ public:
int set17(int index, int v);
void remove(int index);
void reset();
+ void refresh() {
+ // TODO
+ }
};
class MadsDirtyArea {
@@ -289,7 +371,8 @@ public:
void merge(int startIndex, int count);
bool intersects(int idx1, int idx2);
void mergeAreas(int idx1, int idx2);
- void copy(M4Surface *dest, M4Surface *src, int yOffset);
+ void copy(M4Surface *dest, M4Surface *src, const Common::Point &posAdjust);
+ void clear();
};
enum SpriteAnimType {ANIMTYPE_CYCLED = 1, ANIMTYPE_REVERSIBLE = 2};
@@ -308,8 +391,7 @@ struct MadsSequenceSubEntries {
struct MadsSequenceEntry {
int8 active;
int8 spriteListIndex;
-
- int field_2;
+ bool flipped;
int frameIndex;
int frameStart;
@@ -349,9 +431,9 @@ 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 msgX, int msgY, bool nonFixed, char scale, uint8 depth, int frameInc, SpriteAnimType animType,
- int numSprites, int frameStart);
+ 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);
@@ -359,6 +441,7 @@ public:
void delay(uint32 v1, uint32 v2);
void setAnimRange(int seqIndex, int startVal, int endVal);
void scan();
+ void setDepth(int seqIndex, int depth);
};
class Animation {
@@ -367,10 +450,11 @@ protected:
public:
Animation(MadsM4Engine *vm);
virtual ~Animation();
- virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *walkSurface, M4Surface *sceneSurface) = 0;
+ 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;
};
@@ -386,9 +470,9 @@ public:
MadsDynamicHotspots _dynamicHotspots;
MadsSequenceList _sequenceList;
MadsDirtyAreas _dirtyAreas;
+ MadsAction _action;
int _textSpacing;
- int _ticksAmount;
uint32 _newTimeout;
int _abortTimers;
int8 _abortTimers2;
@@ -398,12 +482,15 @@ public:
M4Surface *_depthSurface;
M4Surface *_bgSurface;
- int _yOffset;
+ M4Surface *_viewport;
public:
MadsView(View *view);
~MadsView();
void refresh();
+ 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 49a96a6c4a..d4e5502efd 100644
--- a/engines/m4/sprite.h
+++ b/engines/m4/sprite.h
@@ -115,7 +115,7 @@ public:
void loadDeltaRle(Common::SeekableReadStream* rleData, int destX, int destY);
void loadMadsSprite(Common::SeekableReadStream* source);
- byte getTransparentColor() const;
+ byte getTransparencyIndex() const;
protected:
};
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 149b6b6eba..5dcfff4f90 100644
--- a/engines/mohawk/console.cpp
+++ b/engines/mohawk/console.cpp
@@ -28,6 +28,7 @@
#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.h"
@@ -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 7f2e0cb312..f04338239f 100644
--- a/engines/mohawk/detection.cpp
+++ b/engines/mohawk/detection.cpp
@@ -117,882 +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,
- },
-
- // 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
- },
-
- {
- {
- "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,
@@ -1011,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 2ddfb47575..1974aec9c2 100644
--- a/engines/mohawk/graphics.cpp
+++ b/engines/mohawk/graphics.cpp
@@ -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/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 c646855bc7..07b08dc220 100644
--- a/engines/mohawk/riven.cpp
+++ b/engines/mohawk/riven.cpp
@@ -29,6 +29,7 @@
#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"
@@ -37,10 +38,12 @@
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;
@@ -49,20 +52,27 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio
_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() {
@@ -71,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() {
@@ -94,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");
@@ -339,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;
@@ -363,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);
@@ -405,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;
@@ -480,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);
@@ -583,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) {
@@ -618,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 11c3a4c0cb..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,6 +113,7 @@ public:
RivenGraphics *_gfx;
RivenExternal *_externalScriptHandler;
Common::RandomSource *_rnd;
+ RivenScriptManager *_scriptMan;
Card _cardData;
@@ -126,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
diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp
index 4e6bba1c2a..67d621a54c 100644
--- a/engines/mohawk/riven_external.cpp
+++ b/engines/mohawk/riven_external.cpp
@@ -284,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();
}
@@ -299,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();
}
@@ -349,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();
}
@@ -364,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();
}
@@ -380,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();
}
@@ -437,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();
}
@@ -450,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();
}
@@ -662,15 +692,17 @@ 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:
@@ -682,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) {
@@ -960,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) {
@@ -1043,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));
}
}
@@ -1052,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));
}
}
@@ -1061,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));
}
}
@@ -1196,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();
}
@@ -1211,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];
}
diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h
index 14bb51340c..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;
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 d574a455c6..1fcaba8ac0 100644
--- a/engines/mohawk/riven_scripts.cpp
+++ b/engines/mohawk/riven_scripts.cpp
@@ -35,33 +35,21 @@
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) {
@@ -610,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
index a45a4294c8..17456b8ec3 100644
--- a/engines/mohawk/video.cpp
+++ b/engines/mohawk/video.cpp
@@ -342,7 +342,7 @@ VideoHandle VideoManager::createVideoHandle(uint16 id, uint16 x, uint16 y, bool
entry.loop = loop;
entry.enabled = true;
entry->setChunkBeginOffset(_vm->getResourceOffset(ID_TMOV, id));
- entry->load(*_vm->getRawData(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++)
@@ -378,7 +378,7 @@ VideoHandle VideoManager::createVideoHandle(Common::String filename, uint16 x, u
return NULL_VID_HANDLE;
}
- entry->load(*file);
+ entry->load(file);
// Search for any deleted videos so we can take a formerly used slot
for (uint32 i = 0; i < _videoStreams.size(); i++)
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 e145c0da94..1d8724e2d8 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 bc1759ecd7..2990d024d2 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 d6dd9feb19..ca8f358158 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;
@@ -395,7 +394,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
}
}
@@ -412,7 +411,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 151bfd958d..7bbdf79f1c 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -548,6 +548,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 c752c85d4f..470c698a21 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 ed8a9055ba..1b7fa97f8d 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;
@@ -366,8 +352,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
@@ -433,7 +418,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 2549be9403..2432d84faa 100644
--- a/engines/sci/console.cpp
+++ b/engines/sci/console.cpp
@@ -31,23 +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"
@@ -70,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", &engine->_gamestate->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", &_engine->_gamestate->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));
@@ -97,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));
@@ -106,6 +103,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger() {
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));
@@ -151,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));
@@ -168,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();
@@ -243,8 +243,9 @@ 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;
- while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo()) {
+ while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) {
if (videoDecoder->needsUpdate()) {
Graphics::Surface *frame = videoDecoder->decodeNextFrame();
if (frame) {
@@ -258,8 +259,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);
}
@@ -272,15 +275,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");
@@ -316,6 +314,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");
@@ -326,6 +325,7 @@ bool Console::cmdHelp(int argc, const char **argv) {
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");
@@ -370,28 +370,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");
@@ -414,19 +416,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" };
bool hasVocab997 = g_sci->getResMan()->testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS)) ? true : false;
+ Common::String gameVersion = "N/A";
- DebugPrintf("Game ID: %s\n", _engine->getGameID());
+ 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");
@@ -434,12 +436,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;
@@ -482,14 +486,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;
}
@@ -820,7 +824,7 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) {
}
Common::List<ResourceId> *resources = _engine->getResMan()->listResources(kResourceTypeScript);
- sort(resources->begin(), resources->end(), ResourceIdLess());
+ 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());
@@ -829,21 +833,184 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) {
while (itr != resources->end()) {
script = _engine->getResMan()->findResource(*itr, false);
if (!script)
- DebugPrintf("Error: script %d couldn't be loaded\n", itr->number);
+ DebugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber());
- heap = _engine->getResMan()->findResource(*itr, false);
+ heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->getNumber()), false);
if (!heap)
- DebugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->number);
+ 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->number, script->size + heap->size);
+ 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;
}
@@ -870,26 +1037,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;
}
@@ -920,7 +1086,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();
@@ -953,14 +1119,13 @@ 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) {
- _engine->_gamestate->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW;
- _engine->_gamestate->script_abort_flag = 1;
+ _engine->_gamestate->abortScriptProcessing = kAbortRestartGame;;
- return false;
+ return Cmd_Exit(0, 0);
}
bool Console::cmdClassTable(int argc, const char **argv) {
@@ -1031,8 +1196,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]);
}
@@ -1064,6 +1230,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");
@@ -1135,7 +1417,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
@@ -1192,7 +1478,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;
@@ -1217,7 +1503,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:
@@ -1252,9 +1538,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());
@@ -1281,9 +1573,9 @@ 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->getBufSize(), (uint)scr->getBufSize());
+ 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->_buf)));
+ DebugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->getBuf())));
else
DebugPrintf(" Exports: none\n");
@@ -1394,10 +1686,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());
@@ -1413,7 +1709,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;
}
@@ -1421,9 +1717,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;
@@ -1436,21 +1734,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;
}
@@ -1468,28 +1768,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;
}
@@ -1509,7 +1793,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;
}
@@ -1528,9 +1812,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) {
@@ -1552,37 +1835,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 writeSelectorValue
- _engine->_gamestate->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
- _engine->_gamestate->_sound.sfx_remove_song(handle);
- writeSelectorValue(segMan, id, SELECTOR(signal), SIGNAL_OFFSET);
- writeSelectorValue(segMan, id, SELECTOR(nodePtr), 0);
- writeSelectorValue(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;
@@ -1596,36 +1863,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))) {
@@ -1649,7 +1886,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;
}
@@ -1661,10 +1897,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));
}
@@ -1673,11 +1909,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");
@@ -1701,7 +1932,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;
}
@@ -1730,7 +1964,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;
}
@@ -1772,9 +2009,9 @@ bool Console::cmdVMVarlist(int argc, const char **argv) {
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(s->variables_seg[i], s->variables[i] - s->variables_base[i])));
- if (s->variables_max)
- DebugPrintf(" total %d", s->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");
}
@@ -1782,76 +2019,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;
}
EngineState *s = _engine->_gamestate;
- const char *varnames[] = {"global", "local", "temp", "param"};
- const char *varabbrev = "gltp";
- const char *vartype_pre = strchr(varabbrev, *argv[1]);
- int vartype;
- int idx;
-
- if (!vartype_pre) {
+ 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;
- char *endPtr = 0;
- int idxLen = strlen(argv[2]);
- const char *lastChar = argv[2] + idxLen - (idxLen == 0 ? 0 : 1);
+ 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 ((strncmp(argv[2], "0x", 2) == 0) || (*lastChar == 'h')) {
- // hexadecimal number
- idx = strtol(argv[2], &endPtr, 16);
- if ((*endPtr != 0) && (*endPtr != 'h')) {
- DebugPrintf("Invalid hexadecimal index '%s'\n", argv[2]);
+ if (!parseInteger(argv[2], varIndex))
+ return true;
+
+ if (varIndex < 0) {
+ DebugPrintf("Variable number may not be negative\n");
return true;
}
- } else {
- // decimal number
- idx = strtol(argv[2], &endPtr, 10);
- if (*endPtr != 0) {
- DebugPrintf("Invalid decimal index '%s'\n", argv[2]);
+
+ 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;
}
- if (idx < 0) {
- DebugPrintf("Invalid: negative index\n");
- return true;
- }
+ case 4:
+ // acc
+ if (argc > 3) {
+ DebugPrintf("Too many arguments\n");
+ return true;
+ }
+ curValue = &s->r_acc;
+ if (argc == 3)
+ setValue = argv[2];
+ break;
- if ((s->variables_max) && (s->variables_max[vartype] <= idx)) {
- DebugPrintf("Max. index is %d (0x%x)\n", s->variables_max[vartype], s->variables_max[vartype]);
- return true;
+ default:
+ break;
}
- switch (argc) {
- case 3:
- DebugPrintf("%s var %d == %04x:%04x\n", varnames[vartype], idx, PRINT_REG(s->variables[vartype][idx]));
- break;
- case 4:
- if (parse_reg_t(_engine->_gamestate, argv[3], &s->variables[vartype][idx], true)) {
+ 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;
}
- break;
- default:
- DebugPrintf("Too many arguments\n");
}
-
return true;
}
@@ -1901,20 +2157,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;
@@ -1978,7 +2236,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;
}
@@ -1994,47 +2252,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:
@@ -2087,35 +2366,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", _engine->_gamestate->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;
@@ -2126,20 +2382,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;
}
@@ -2158,7 +2419,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)
@@ -2171,35 +2435,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) {
@@ -2209,11 +2479,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) {
@@ -2239,14 +2509,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) {
@@ -2357,11 +2627,11 @@ bool Console::cmdSend(int argc, const char **argv) {
return true;
}
- const char *selector_name = argv[2];
- int selectorId = _engine->getKernel()->findSelector(selector_name);
+ const char *selectorName = argv[2];
+ int selectorId = _engine->getKernel()->findSelector(selectorName);
if (selectorId < 0) {
- DebugPrintf("Unknown selector: \"%s\"\n", selector_name);
+ DebugPrintf("Unknown selector: \"%s\"\n", selectorName);
return true;
}
@@ -2371,10 +2641,10 @@ bool Console::cmdSend(int argc, const char **argv) {
return true;
}
- SelectorType selector_type = lookupSelector(_engine->_gamestate->_segMan, object, selectorId, 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;
}
@@ -2411,7 +2681,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);
}
@@ -2426,19 +2696,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) {
@@ -2454,6 +2749,9 @@ bool Console::cmdBreakpointList(int argc, const char **argv) {
i++;
}
+ if (!i)
+ DebugPrintf(" No breakpoints defined.\n");
+
return true;
}
@@ -2461,14 +2759,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
}
@@ -2479,23 +2784,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]);
@@ -2509,13 +2814,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::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::cmdBreakpointExecFunction(int argc, const char **argv) {
+bool Console::cmdBreakpointFunction(int argc, const char **argv) {
// TODO/FIXME: Why does this accept 2 parameters (the high and the low part of the address)?"
if (argc != 3) {
DebugPrintf("Sets a breakpoint on the execution of the specified exported function.\n");
@@ -2530,8 +2851,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;
}
@@ -2731,16 +3052,16 @@ bool Console::cmdQuit(int argc, const char **argv) {
if (!scumm_stricmp(argv[1], "game")) {
// Quit gracefully
- _engine->_gamestate->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) {
@@ -2980,8 +3301,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");
@@ -3008,9 +3392,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");
}
@@ -3076,7 +3460,7 @@ int Console::printObject(reg_t pos) {
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);
@@ -3095,12 +3479,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: %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 2b13e03ef6..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);
@@ -74,6 +75,7 @@ private:
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);
@@ -117,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);
@@ -128,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);
@@ -145,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 1ccfc6bf02..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,83 @@ 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;
@@ -198,6 +277,12 @@ static const OldNewIdTableEntry s_oldNewTable[] = {
{ "", "", 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();
@@ -214,7 +299,7 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R
if (sierraId == "fp" || sierraId == "gk" || sierraId == "pq4")
demoThreshold = 150;
- Common::List<ResourceId> *resources = resMan->listResources(kResourceTypeScript, -1);
+ Common::ScopedPtr<Common::List<ResourceId> > resources(resMan->listResources(kResourceTypeScript, -1));
if (resources->size() < demoThreshold) {
*gameFlags |= ADGF_DEMO;
@@ -251,7 +336,7 @@ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, R
// or qfg4 full (SCI2)
// qfg1 VGA doesn't have view 1
if (!resMan->testResource(ResourceId(kResourceTypeView, 1)))
- return "qfg1";
+ return "qfg1vga";
// qfg4 full is SCI2
if (getSciVersion() == SCI_VERSION_2)
@@ -295,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)
@@ -305,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 {
@@ -407,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
@@ -419,7 +508,12 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
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
@@ -497,7 +591,7 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
!strcmp(s_fallbackDesc.gameid, "sq1sci"))
s_fallbackDesc.extra = "VGA Remake";
- if (!strcmp(s_fallbackDesc.gameid, "qfg1") && getSciVersion() == SCI_VERSION_1_1)
+ if (!strcmp(s_fallbackDesc.gameid, "qfg1vga") && getSciVersion() == SCI_VERSION_1_1)
s_fallbackDesc.extra = "VGA Remake";
// Add "demo" to the description for demos
@@ -509,12 +603,16 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl
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 {
@@ -529,9 +627,16 @@ bool SciMetaEngine::hasFeature(MetaEngineFeature f) const {
bool SciEngine::hasFeature(EngineFeature f) const {
return
- //(f == kSupportsRTL) ||
- (f == kSupportsLoadingDuringRuntime) ||
- (f == kSupportsSavingDuringRuntime);
+ (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 {
@@ -652,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 {
@@ -668,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 48f7c2d64f..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 (lookupSelector(_segMan, objAddr, slc, NULL, &addr) != kSelectorMethod) {
- warning("getDetectionAddr: target selector is not a method of object %s", objName.c_str());
+ 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->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.
+ // 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,7 +230,7 @@ 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
@@ -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");
- const 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,7 +331,7 @@ 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
@@ -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;
}
@@ -343,33 +369,36 @@ SciVersion GameFeatures::detectGfxFunctionsType() {
bool searchRoomObj = false;
reg_t rmObjAddr = _segMan->findObjectByName("Rm");
- if (_kernel->_selectorCache.overlay != -1) {
- // The game has an overlay selector, check how it calls kDrawPicto determine
- // the graphics functions type used
- if (lookupSelector(_segMan, rmObjAddr, _kernel->_selectorCache.overlay, NULL, NULL) == kSelectorMethod) {
+ 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)
+ // 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
+ // 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
+ // The game doesn't have an overlay selector, so search for it
+ // manually
searchRoomObj = true;
}
if (searchRoomObj) {
- // If requested, check if any method of the Rm object is calling kDrawPic,
- // as the overlay selector might be missing in demos
+ // 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;
const Object *obj = _segMan->getObject(rmObjAddr);
@@ -380,8 +409,9 @@ SciVersion GameFeatures::detectGfxFunctionsType() {
}
if (!found) {
- // No method of the Rm object is calling kDrawPic, thus the game
- // doesn't have overlays and is using older 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;
}
}
@@ -393,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;
@@ -408,7 +488,7 @@ 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
@@ -419,9 +499,11 @@ bool GameFeatures::autoDetectSci21KernelType() {
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;
@@ -448,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;
@@ -461,7 +543,7 @@ 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
@@ -491,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 bc10099e52..0000000000
--- a/engines/sci/engine/game.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 "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 {
-
-#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->_segMan->initSysStrings();
-
- 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;
- }
-
- // Reset parser
- Vocabulary *voc = g_sci->getVocabulary();
- if (voc) {
- voc->parserIsValid = false; // Invalidate parser
- voc->parser_event = NULL_REG; // Invalidate parser event
- voc->parser_base = make_reg(s->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE);
- }
-
- // Initialize menu TODO: Actually this should be another init()
- if (g_sci->_gfxMenu)
- g_sci->_gfxMenu->reset();
-
- s->restoring = false;
-
- s->game_start_time = g_system->getMillis();
- s->last_wait_time = s->game_start_time;
-
- srand(g_system->getMillis()); // Initialize random number generator
-
- s->_gameObj = g_sci->getResMan()->findGameObject();
-
-#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) {
- if (!s->restoring) {
- s->_executionStack.clear();
-#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 6ebee2dfbd..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("MergePoly", kMergePoly, "rli"),
- DEFUN("ResCheck", kResCheck, "iii*"),
- DEFUN("SetQuitStr", kSetQuitStr, "r"),
- DEFUN("ShowMovie", kShowMovie, ".*"),
- DEFUN("SetVideoMode", kSetVideoMode, "i"),
- DEFUN("Platform", kPlatform, ".*"),
- 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, "i.*"),
-
- // 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("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).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 8f8f34f74e..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 ********************/
@@ -423,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
@@ -430,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);
@@ -451,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 0afdc3f2eb..0000000000
--- a/engines/sci/engine/kernel32.cpp
+++ /dev/null
@@ -1,823 +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 readSelector(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)
- 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();
- if ((uint32)s->_segMan->sysStrings->_strings[sysStringId]._maxSize < index1 + count) {
- free(s->_segMan->sysStrings->_strings[sysStringId]._value);
- s->_segMan->sysStrings->_strings[sysStringId]._maxSize = index1 + count;
- s->_segMan->sysStrings->_strings[sysStringId]._value = (char *)calloc(index1 + count, sizeof(char));
- }
-
- strncpy(s->_segMan->sysStrings->_strings[sysStringId]._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;
-}
-
-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 = 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;
- */
-
- // 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 = 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));
-
- //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
- 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)));
- 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 fd7711f196..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,7 +41,7 @@ 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;
@@ -52,6 +50,10 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
// 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
@@ -67,7 +69,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
oldx = mousePos.x;
oldy = mousePos.y;
- curEvent = s->_event->get(mask);
+ curEvent = g_sci->getEventManager()->getSciEvent(mask);
if (g_sci->getVocabulary())
g_sci->getVocabulary()->parser_event = NULL_REG; // Invalidate parser event
@@ -79,7 +81,9 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) {
switch (curEvent.type) {
case SCI_EVENT_QUIT:
- quit_vm(s);
+ s->abortScriptProcessing = kAbortQuitGame; // Terminate VM
+ g_sci->_debugState.seeking = kDebugSeekNothing;
+ g_sci->_debugState.runningStep = 0;
break;
case SCI_EVENT_KEYBOARD:
@@ -124,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");
@@ -149,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;
}
@@ -203,7 +205,10 @@ reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) {
}
if (mover >= 0) {
- writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_JOYSTICK);
+ 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
@@ -214,7 +219,7 @@ 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;
@@ -233,7 +238,7 @@ 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;
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 3e0ecd1a28..39c32ccc68 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -36,12 +36,9 @@
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;
@@ -101,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;
@@ -115,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();
@@ -133,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
@@ -163,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);
}
@@ -171,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) {
@@ -200,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)
@@ -221,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;
@@ -244,66 +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 bool _savegame_index_struct_compare(const SavegameDesc &l, const SavegameDesc &r) {
- if (l.date != r.date)
- return (l.date > r.date);
- return (l.time > r.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) || 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 wouldnt 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_index_struct_compare);
-}
-
-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;
+ debugC(2, kDebugLevelFile, " -> FGets'ed \"%s\"", dest);
}
reg_t kFGets(EngineState *s, int argc, reg_t *argv) {
@@ -311,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];
@@ -326,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,
@@ -342,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) {
@@ -389,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;
}
@@ -421,41 +373,140 @@ reg_t kGetSaveDir(EngineState *s, int argc, reg_t *argv) {
}
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]);
- uint16 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);
- // Check for savegame slot being out of range
- if (savedir_nr >= saves.size())
+ // 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;
+
+ // 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;
// Check for compatible savegame version
- int ver = saves[savedir_nr].version;
+ int ver = saves[savegameNr].version;
if (ver < MINIMUM_SAVEGAME_VERSION || ver > CURRENT_SAVEGAME_VERSION)
return NULL_REG;
// Otherwise we assume the savegame is OK
- return make_reg(0, 1);
+ return TRUE_REG;
}
reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) {
@@ -463,9 +514,12 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) {
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);
reg_t *slot = s->_segMan->derefRegPtr(argv[2], totalSaves);
@@ -480,7 +534,7 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) {
char *saveNamePtr = saveNames;
for (uint i = 0; i < totalSaves; i++) {
- *slot++ = make_reg(0, i); // Store slot
+ *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;
}
@@ -495,46 +549,57 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) {
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))) {
@@ -543,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 {
@@ -563,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;
}
@@ -605,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) {
@@ -642,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);
}
@@ -666,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 abe55455de..e1e92b1cf9 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -23,22 +23,21 @@
*
*/
+#include "common/system.h"
+
#include "engines/util.h"
#include "graphics/cursorman.h"
-#include "graphics/video/avi_decoder.h"
-#include "graphics/video/qt_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"
@@ -46,9 +45,15 @@
#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 {
@@ -127,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();
@@ -143,14 +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;
- // In SCI32, the right parameter seems to be divided by 2
- if (getSciVersion() >= SCI_VERSION_2)
- right *= 2;
+ 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);
@@ -160,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:
@@ -170,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;
@@ -184,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;
}
}
@@ -205,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]);
@@ -343,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);
@@ -392,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) {
@@ -528,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 (!strcmp(g_sci->getGameID(), "lsl1sci") && s->currentRoomNumber() == 300) {
- int top = readSelectorValue(s->_segMan, object, SELECTOR(brTop));
- writeSelectorValue(s->_segMan, object, SELECTOR(brTop), top + 2);
- }
-
return s->r_acc;
}
@@ -545,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();
@@ -611,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;
@@ -698,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;
}
@@ -715,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;
@@ -790,6 +807,11 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
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;
@@ -801,11 +823,8 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
loopNo = (l & 0x80) ? l - 256 : l;
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 (!strcmp(g_sci->getGameID(), "jones"))
+ // 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;
@@ -821,12 +840,12 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) {
maxChars = readSelectorValue(s->_segMan, controlObject, SELECTOR(x)); // max chars per entry
cursorOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(cursor));
- if (g_sci->getKernel()->_selectorCache.topString != -1) {
+ if (SELECTOR(topString) != -1) {
// Games from early SCI1 onwards use topString
upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(topString));
} else {
// Earlier games use lsTop or brTop
- if (lookupSelector(s->_segMan, controlObject, g_sci->getKernel()->_selectorCache.brTop, NULL, NULL) == kSelectorVariable)
+ if (lookupSelector(s->_segMan, controlObject, SELECTOR(brTop), NULL, NULL) == kSelectorVariable)
upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(brTop));
else
upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(lsTop));
@@ -879,10 +898,41 @@ 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") {
+ // "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);
return NULL_REG;
@@ -960,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;
@@ -986,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 (!strcmp(g_sci->getGameID(), "freddypharkas") || !strcmp(g_sci->getGameID(), "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 (!strcmp(g_sci->getGameID(), "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;
}
@@ -1049,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;
@@ -1062,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;
}
@@ -1083,122 +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 = g_sci->_gfxCursor->isVisible();
- if (reshowCursor)
- g_sci->_gfxCursor->kernelHide();
+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
- uint16 screenWidth = g_system->getWidth();
- uint16 screenHeight = g_system->getHeight();
-
- Graphics::VideoDecoder *videoDecoder = 0;
+ //warning("STUB: SetVideoMode %d", argv[0].toUint16());
+ return s->r_acc;
+}
- if (argv[0].segment != 0) {
- Common::String filename = s->_segMan->getString(argv[0]);
+// 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;
+}
- if (g_sci->getPlatform() == Common::kPlatformMacintosh) {
- // Mac QuickTime
- // The only argument is the string for the video
+reg_t kTextColors(EngineState *s, int argc, reg_t *argv) {
+ g_sci->_gfxText16->kernelTextColors(argc, argv);
+ return s->r_acc;
+}
- // HACK: Switch to 16bpp graphics for Cinepak.
- initGraphics(screenWidth, screenHeight, screenWidth > 320, NULL);
+#ifdef ENABLE_SCI32
- if (g_system->getScreenFormat().bytesPerPixel == 1) {
- warning("This video requires >8bpp color to be displayed, but could not switch to RGB color mode.");
- return NULL_REG;
- }
+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);
- 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.
+ return make_reg(0, 1);
+}
-#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());
- }
- }
+// 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;
+}
- if (videoDecoder) {
- uint16 x = (screenWidth - videoDecoder->getWidth()) / 2;
- uint16 y = (screenHeight - videoDecoder->getHeight()) / 2;
+reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv) {
+ reg_t viewObj = argv[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);
+ g_sci->_gfxFrameout->kernelAddScreenItem(viewObj);
+ return NULL_REG;
+}
- if (videoDecoder->hasDirtyPalette())
- videoDecoder->setSystemPalette();
+reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv) {
+ //reg_t viewObj = argv[0];
- g_system->updateScreen();
- }
- }
+ //warning("kUpdateScreenItem, object %04x:%04x, view %d, loop %d, cel %d, pri %d", PRINT_REG(viewObj), viewId, loopNo, celNo, priority);
+ return NULL_REG;
+}
- Common::Event event;
- while (g_system->getEventManager()->pollEvent(event))
- ;
+reg_t kDeleteScreenItem(EngineState *s, int argc, reg_t *argv) {
+ reg_t viewObj = argv[0];
- g_system->delayMillis(10);
- }
+ g_sci->_gfxFrameout->kernelDeleteScreenItem(viewObj);
- // 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();
-
- delete videoDecoder;
- }
+ /*
+ 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;
+ */
+
+ // TODO
- if (reshowCursor)
- g_sci->_gfxCursor->kernelShow();
+ //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();
@@ -1211,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);
@@ -1228,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 f06f3eec77..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,66 +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;
}
reg_t kNewNode(EngineState *s, int argc, reg_t *argv) {
reg_t nodeValue = argv[0];
- reg_t nodeKey = (argc == 2) ? argv[1] : NULL_REG;
+ // 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);
- 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;
}
@@ -169,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;
}
@@ -183,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;
}
@@ -197,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(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 = 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(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 = 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) {
@@ -274,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;
@@ -305,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];
@@ -352,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
}
@@ -398,8 +393,6 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) {
reg_t order_func = argv[2];
int input_size = (int16)readSelectorValue(segMan, source, SELECTOR(size));
- int i;
-
reg_t input_data = readSelector(segMan, source, SELECTOR(elements));
reg_t output_data = readSelector(segMan, dest, SELECTOR(elements));
@@ -422,9 +415,10 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) {
sort_temp_t *temp_array = (sort_temp_t *)malloc(sizeof(sort_temp_t) * input_size);
- i = 0;
+ int i = 0;
while (node) {
- invokeSelector(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;
@@ -436,7 +430,7 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) {
for (i = 0;i < input_size;i++) {
reg_t lNode = s->_segMan->newNode(temp_array[i].value, temp_array[i].key);
- _k_add_to_end(s, output_data, lNode);
+ addToEnd(s, output_data, lNode);
}
free(temp_array);
@@ -449,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);
@@ -518,12 +512,12 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) {
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 {
writeSelector(s->_segMan, curObject, slc, argv[2]);
}
} else {
- invokeSelectorArgv(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);
@@ -550,9 +544,9 @@ reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv) {
// First, check if the target selector is a variable
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 {
- invokeSelectorArgv(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())
@@ -584,9 +578,9 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) {
// First, check if the target selector is a variable
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 {
- invokeSelectorArgv(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())
@@ -599,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 f91ba0fd82..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->shrinkStackToBase();
- s->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 (!strcmp(g_sci->getGameID(), "lsl3") && s->currentRoomNumber() == 290)
- s->_throttleTrigger = true;
- if (!strcmp(g_sci->getGameID(), "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 : {
@@ -261,7 +270,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 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)
@@ -277,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;
}
@@ -335,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;
}
@@ -371,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 499aeabcc6..4becc6f415 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
@@ -266,6 +268,15 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
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()) {
@@ -303,8 +314,15 @@ 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;
+
+ // Sanity check: make sure that destx, desty are inside the screen coordinates.
+ // They can go off screen in some cases, e.g. in SQ5 while scrubbing the floor
+ if (destx < g_sci->_gfxScreen->getWidth() && desty < g_sci->_gfxScreen->getHeight()) {
+ x = destx;
+ y = desty;
+ } else {
+ warning("kDoBresen: destination x, y would be off-screen(%d, %d)", destx, desty);
+ }
completed = 1;
debugC(2, kDebugLevelBresen, "Finished mover %04x:%04x", PRINT_REG(mover));
@@ -315,14 +333,24 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
debugC(2, kDebugLevelBresen, "New data: (x,y)=(%d,%d), di=%d", x, y, bdi);
- if (g_sci->getKernel()->_selectorCache.cantBeHere != -1) {
- invokeSelector(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 {
- invokeSelector(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
+ if (collision) {
signal = readSelectorValue(segMan, client, SELECTOR(signal));
writeSelectorValue(segMan, client, SELECTOR(x), oldx);
@@ -330,13 +358,16 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
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
}
if ((getSciVersion() >= SCI_VERSION_1_EGA))
if (completed)
- invokeSelector(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);
}
@@ -373,14 +404,14 @@ 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 = 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;
}
@@ -389,7 +420,7 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) {
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;
}
@@ -399,20 +430,13 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) {
debugC(2, kDebugLevelBresen, "Doing avoider %04x:%04x (dest=%d,%d)", PRINT_REG(avoider), destx, desty);
- if (invokeSelector(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 = readSelector(segMan, client, SELECTOR(mover));
if (!mover.segment) // Mover has been disposed?
return s->r_acc; // Return gracefully.
- if (invokeSelector(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 - readSelectorValue(segMan, client, SELECTOR(x));
dy = desty - readSelectorValue(segMan, client, SELECTOR(y));
@@ -421,7 +445,7 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) {
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 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));
@@ -439,11 +463,7 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) {
debugC(2, kDebugLevelBresen, "Pos (%d,%d): Trying angle %d; delta=(%d,%d)", oldx, oldy, angle, move_x, move_y);
- if (invokeSelector(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);
writeSelectorValue(segMan, client, SELECTOR(x), oldx);
writeSelectorValue(segMan, client, SELECTOR(y), oldy);
@@ -461,7 +481,7 @@ 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 = readSelectorValue(segMan, client, SELECTOR(heading));
@@ -472,12 +492,11 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) {
s->r_acc = make_reg(0, angle);
+ reg_t params[2] = { make_reg(0, angle), client };
+
if (looper.segment) {
- if (invokeSelector(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 785ff39d22..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 {
/*************************************************************/
@@ -60,8 +62,8 @@ 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 (voc->parser_event.isNull() || (readSelectorValue(s->_segMan, voc->parser_event, SELECTOR(claimed)))) {
@@ -93,9 +95,10 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) {
char *error;
ResultWordList words;
reg_t event = argv[1];
+ 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);
voc->parserIsValid = false; /* not valid */
@@ -106,7 +109,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) {
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);
@@ -118,7 +121,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) {
s->r_acc = make_reg(0, 1);
writeSelectorValue(segMan, event, SELECTOR(claimed), 1);
- invokeSelector(INV_SEL(s, s->_gameObj, syntaxFail, kStopOnInvalidSelector), 2, voc->parser_base, stringpos);
+ invokeSelector(s, g_sci->getGameObject(), SELECTOR(syntaxFail), argc, argv, 2, params);
/* Issue warning */
debugC(2, kDebugLevelParser, "Tree building failed");
@@ -141,7 +144,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) {
debugC(2, kDebugLevelParser, "Word unknown: %s", error);
/* Issue warning: */
- invokeSelector(INV_SEL(s, s->_gameObj, wordFail, kStopOnInvalidSelector), 2, 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 */
}
diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp
index 857ccc2a08..fdebc0599c 100644
--- a/engines/sci/engine/kpathing.cpp
+++ b/engines/sci/engine/kpathing.cpp
@@ -436,33 +436,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 +481,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 +561,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 +581,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 +600,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 +673,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 +730,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 +777,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 +818,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 +933,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 +946,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 +989,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 +1018,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,11 +1068,13 @@ 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 = readSelector(segMan, polygon, SELECTOR(points));
@@ -1056,7 +1097,7 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) {
// WORKAROUND: broken polygon in lsl1sci, room 350, after opening elevator
// Polygon has 17 points but size is set to 19
- if ((size == 19) && !strcmp(g_sci->getGameID(), "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 +1115,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 +1139,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;
@@ -1174,7 +1219,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 (!strcmp(g_sci->getGameID(), "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 +1322,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 +1342,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;
@@ -1694,17 +1741,14 @@ 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.
+/**
+ * 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];
-
- // TODO: actually merge the polygon
- // In QFG1VGA, there are no immediately visible side-effects
- // of this being a stub.
-
-#if 0
List *list = s->_segMan->lookupList(argv[1]);
Node *node = s->_segMan->lookupNode(list->first);
// List size is not needed
@@ -1723,9 +1767,23 @@ reg_t kMergePoly(EngineState *s, int argc, reg_t *argv) {
}
#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;
+}
- return polygonData;
+#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 722d0175d1..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) {
@@ -155,24 +188,10 @@ reg_t kDisposeClone(EngineState *s, int argc, reg_t *argv) {
}
if (!victim_obj->isClone()) {
- //warning("Attempt to dispose something other than a clone at %04x", offset);
// SCI silently ignores this behaviour; some games actually depend on it
return s->r_acc;
}
- // QFG3 clears clones with underbits set
- //if (readSelectorValue(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;
@@ -198,9 +217,10 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) {
// 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
+ // as no return value is expected. If an export is requested, then
+ // it will most certainly fail with OOB access.
if (argc == 2)
- warning("Script 0x%x does not have a dispatch table and export %d "
+ error("Script 0x%x does not have a dispatch table and export %d "
"was requested from it", script, index);
return NULL_REG;
}
@@ -222,10 +242,6 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) {
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) {
@@ -233,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];
}
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 2681b612e9..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;
}
}
}
@@ -141,19 +143,22 @@ reg_t kReadNumber(EngineState *s, int argc, reg_t *argv) {
int16 result = 0;
if (*source == '$') {
- // hexadecimal input
+ // Hexadecimal input
result = (int16)strtol(source + 1, NULL, 16);
} else {
- // decimal input, we can not use strtol/atoi in here, because sierra used atoi BUT it was a non standard compliant
- // atoi, that didnt do clipping. In SQ4 we get the door code in here and that's even larger than uint32!
+ // 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')) {
- // Sierras atoi stopped processing at anything different than number
- // Sometimes the input has a trailing space, that's fine (example: lsl3)
+ // 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
@@ -423,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]);
@@ -560,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;
}
@@ -578,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..3ad2d95f58
--- /dev/null
+++ b/engines/sci/engine/kvideo.cpp
@@ -0,0 +1,303 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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 "sci/video/vmd_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;
+
+ 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 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 9bf23dedf5..a7716516e7 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.syncString(tmp, VER(14), VER(23)); // OBSOLETE: Used to be game_version
- 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
-
- 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.skip(4, VER(9), VER(19)); // OBSOLETE: Used to be _numExports
- s.skip(4, VER(9), VER(19)); // OBSOLETE: Used to be _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);
@@ -622,30 +444,6 @@ void DataStack::saveLoadWithSerializer(Common::Serializer &s) {
#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,43 +555,49 @@ 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);
+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);
+ }
+ s.syncBytes(palette->intensity, 256);
+}
- 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);
+void GfxPalette::saveLoadWithSerializer(Common::Serializer &s) {
+ if (s.getVersion() < 24)
+ return;
- if (s->execution_stack_base) {
- warning("Cannot save from below kernel function");
- return 1;
+ if (s.isLoading() && _palVaryResourceId != -1)
+ palVaryRemoveTimer();
+
+ 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);
}
- Common::Serializer ser(0, fh);
- sync_SavegameMetadata(ser, meta);
- Graphics::saveThumbnail(*fh);
- s->saveLoadWithSerializer(ser); // FIXME: Error handling?
-
- return 0;
+ 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;
}
-// 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;
@@ -761,7 +610,7 @@ void SegManager::reconstructScripts(EngineState *s) {
scr->_localsBlock = (scr->_localsSegment == 0) ? NULL : (LocalVariables *)(_heap[scr->_localsSegment]);
for (ObjMap::iterator it = scr->_objects.begin(); it != scr->_objects.end(); ++it)
- it->_value._baseObj = scr->_buf + it->_value.getPos().offset;
+ it->_value._baseObj = scr->getBuf(it->_value.getPos().offset);
}
for (i = 0; i < _heap.size(); i++) {
@@ -776,6 +625,8 @@ void SegManager::reconstructScripts(EngineState *s) {
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);
}
@@ -784,47 +635,71 @@ void SegManager::reconstructScripts(EngineState *s) {
}
}
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-static void reconstruct_sounds(EngineState *s) {
- Song *seeker;
- SongIteratorType it_type;
+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;
+
+ 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];
+ const Object *baseObj = getObject(seeker.getSpeciesSelector());
+ seeker.cloneFromObject(baseObj);
+ if (!baseObj)
+ error("Clone entry without a base class: %d", j);
+ } // end for
+ } // end if
+ } // end for
+}
+
- if (getSciVersion() > SCI_VERSION_01)
- it_type = SCI_SONG_ITERATOR_TYPE_SCI1;
- else
- it_type = SCI_SONG_ITERATOR_TYPE_SCI0;
+#pragma mark -
- seeker = s->_sound._songlib._lib;
- while (seeker) {
- SongIterator *base, *ff = 0;
- int oldstatus;
- SongIterator::Message msg;
+bool gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename, const char *version) {
+ TimeDate curTime;
+ g_system->getTimeAndDate(curTime);
- 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();
+ 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);
- 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);
+ Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false);
+ meta.script0_size = script0->size;
+ meta.game_object_offset = g_sci->getGameObject().offset;
- oldstatus = seeker->_status;
- seeker->_status = SOUND_STATUS_STOPPED;
- seeker->_it = ff;
- s->_sound.sfx_song_set_status(seeker->_handle, oldstatus);
- seeker = seeker->_next;
+ // 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) {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- SongLibrary temp;
-#endif
-
SavegameMetadata meta;
Common::Serializer ser(fh, 0);
@@ -837,86 +712,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;
+ 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");
+
+ GUI::MessageDialog dialog("This saved game was created with a different version of the game, unable to load it", "OK");
+ dialog.runModal();
+
+ s->r_acc = make_reg(0, 1); // signal failure
+ return;
+ }
}
+ // We don't need the thumbnail here, so just read it and discard it
+ Graphics::skipThumbnail(*fh);
+
s->reset(true);
s->saveLoadWithSerializer(ser); // FIXME: Error handling?
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- s->_sound.sfx_exit();
-#endif
-
- // Set exec stack base to zero
- s->execution_stack_base = 0;
-
// Now copy all current state information
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- temp = s->_sound._songlib;
- s->_sound.sfx_init(g_sci->getResMan(), s->sfx_init_flags, g_sci->_features->detectDoSoundType());
- s->sfx_init_flags = s->sfx_init_flags;
- s->_sound._songlib.freeSounds();
- s->_sound._songlib = temp;
- s->_soundCmd->updateSfxState(&retval->_sound);
-#endif
-
- reconstruct_stack(s);
+ s->_segMan->reconstructStack(s);
s->_segMan->reconstructScripts(s);
s->_segMan->reconstructClones();
- s->_gameObj = s->_gameObj;
- s->script_000 = s->_segMan->getScript(s->_segMan->getScriptSegment(0, SCRIPT_GET_DONT_LOAD));
- s->gc_countdown = GC_INTERVAL - 1;
+ s->initGlobals();
+ s->gcCountDown = GC_INTERVAL - 1;
// Time state:
- s->last_wait_time = g_system->getMillis();
- s->game_start_time = g_system->getMillis();
-
- s->restoring = false;
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- s->_sound._it = NULL;
- s->_sound._flags = s->_sound._flags;
- s->_sound._song = NULL;
- s->_sound._suspended = s->_sound._suspended;
- reconstruct_sounds(s);
-#else
- s->_soundCmd->reconstructPlayList(meta.savegame_version);
-#endif
+ s->lastWaitTime = g_system->getMillis();
+ s->gameStartTime = g_system->getMillis();
+ s->_screenUpdateTime = g_system->getMillis();
+
+ if (g_sci->_gfxPorts)
+ g_sci->_gfxPorts->reset();
+
+ g_sci->_soundCmd->reconstructPlayList(meta.savegame_version);
// Message state:
+ delete s->_msgState;
s->_msgState = new MessageState(s->_segMan);
-#ifdef ENABLE_SCI32
- if (g_sci->_gui32) {
- g_sci->_gui32->init();
- } else {
-#endif
- g_sci->_gui->resetEngineState(s);
- g_sci->_gui->init(g_sci->_features->usesOldGfxFunctions());
-#ifdef ENABLE_SCI32
- }
-#endif
-
+ s->abortScriptProcessing = kAbortLoadGame;
- s->restoring = true;
- s->script_abort_flag = 2; // Abort current game with replay
- s->shrinkStackToBase();
+ // 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 7be05381da..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 = 20,
- 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 1f32e50b67..645094d9ec 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -35,431 +35,561 @@
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);
+
+ if (getSciVersion() >= SCI_VERSION_1_1) {
+ Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0);
+ assert(heap != 0);
- for (uint16 classNr = 0; classNr < totalClasses; classNr++) {
- uint16 scriptNr = READ_SCI11ENDIAN_UINT16(vocab996->data + classNr * 4 + 2);
+ _heapStart = _buf + _scriptSize;
- _classTable[classNr].reg = NULL_REG;
- _classTable[classNr].script = scriptNr;
+ assert(_bufSize - _scriptSize <= heap->size);
+ memcpy(_heapStart, heap->data, heap->size);
}
- _resMan->unlockResource(vocab996);
-}
+ _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 {
+ _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
+ }
+ }
-reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller) {
- if (classnr == 0xffff)
- return NULL_REG;
+ if (getSciVersion() > SCI_VERSION_0_EARLY) {
+ // Does the script actually have locals? If not, set the locals offset to 0
+ if (!_localsCount)
+ _localsOffset = 0;
- 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;
+ 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 {
- Class *the_class = &_classTable[classnr];
- if (!the_class->reg.segment) {
- getScriptSegment(the_class->script, lock);
+ // 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
+ }
+}
- 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();
+Object *Script::getObject(uint16 offset) {
+ if (_objects.contains(offset))
+ return &_objects[offset];
+ else
+ return 0;
+}
- return the_class->reg;
- }
+const Object *Script::getObject(uint16 offset) const {
+ if (_objects.contains(offset))
+ return &_objects[offset];
+ else
+ return 0;
}
-void SegManager::scriptInitialiseLocalsZero(SegmentId seg, int count) {
- Script *scr = getScript(seg);
+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)
- scr->_localsOffset = -count * 2; // Make sure it's invalid
+ VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n");
- LocalVariables *locals = allocLocalsSegment(scr, count);
- if (locals) {
- for (int i = 0; i < count; i++)
- locals->_locals[i] = NULL_REG;
- }
+ VERIFY(obj_pos.offset + kOffsetFunctionArea < (int)_bufSize, "Function area pointer stored beyond end of script\n");
+
+ // 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);
+
+ return obj;
}
-void SegManager::scriptInitialiseLocals(reg_t location) {
- Script *scr = getScript(location.segment);
- unsigned int count;
+void Script::scriptObjRemove(reg_t obj_pos) {
+ if (getSciVersion() < SCI_VERSION_1_1)
+ obj_pos.offset += 8;
- VERIFY(location.offset + 1 < (uint16)scr->getBufSize(), "Locals beyond end of script\n");
+ _objects.erase(obj_pos.toUint16());
+}
- 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
+// 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;
- scr->_localsOffset = location.offset;
+ if (rel < 0)
+ return false;
- if (!(location.offset + count * 2 + 1 < scr->getBufSize())) {
- warning("Locals extend beyond end of script: offset %04x, count %x vs size %x", location.offset, count, (uint)scr->getBufSize());
- count = (scr->getBufSize() - location.offset) >> 1;
- }
+ uint idx = rel >> 1;
- LocalVariables *locals = allocLocalsSegment(scr, count);
- if (locals) {
- uint i;
- const byte *base = (const byte *)(scr->_buf + location.offset);
+ if (idx >= block.size())
+ return false;
- for (i = 0; i < count; i++)
- locals->_locals[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(base + i * 2));
+ 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);
- const 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) & kInfoFlagClass) { // -info- selector
- 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 = make_reg(seg, seeker - scr->_buf);
- Object *obj = scr->scriptObjInit(reg);
-
- // Copy base from species class, as we need its selector IDs
- obj->setSuperClassSelector(
- 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();
- Object *classObj = getObject(classObject);
- obj->setPropDictSelector(classObj->getPropDictSelector());
+ 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");
}
- // 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_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) {
- int objType;
- uint32 objLength = 0;
- bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
- uint16 curOffset = oldScriptHeader ? 2 : 0;
+void Script::incrementLockers() {
+ _lockers++;
+}
- 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 localsCount = READ_LE_UINT16(scr->_buf);
- if (localsCount)
- segMan->scriptInitialiseLocalsZero(segmentId, localsCount);
- }
+void Script::decrementLockers() {
+ if (_lockers > 0)
+ _lockers--;
+}
- // Now do a first pass through the script objects to find the
- // local variable blocks
+int Script::getLockers() const {
+ return _lockers;
+}
- do {
- objType = scr->getHeap(curOffset);
- if (!objType)
- break;
+void Script::setLockers(int lockers) {
+ _lockers = lockers;
+}
- objLength = scr->getHeap(curOffset + 2);
- curOffset += 4; // skip header
+uint16 Script::validateExportFunc(int pubfunct) {
+ bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE);
- switch (objType) {
- case SCI_OBJ_LOCALVARS:
- segMan->scriptInitialiseLocals(make_reg(segmentId, curOffset));
- break;
- 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->classTableSize()) {
- if (species == (int)segMan->classTableSize()) {
- // Happens in the LSL2 demo
- warning("Applying workaround for an off-by-one invalid species access");
- segMan->resizeClassTable(segMan->classTableSize() + 1);
- } else {
- error("Invalid species %d(0x%x) not in interval "
- "[0,%d) while instantiating script at segment %d\n",
- species, species, segMan->classTableSize(),
- segmentId);
- return;
- }
- }
+ if (_numExports <= pubfunct) {
+ error("validateExportFunc(): pubfunct is invalid");
+ return 0;
+ }
- segMan->setClassOffset(species, make_reg(segmentId, classpos));
- // Set technical class position-- into the block allocated for it
- }
- break;
+ if (exportsAreWide)
+ pubfunct *= 2;
+ uint16 offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct);
+ VERIFY(offset < _bufSize, "invalid export function pointer");
- default:
- break;
- }
+ return offset;
+}
- curOffset += objLength - 4;
- } while (objType != 0 && curOffset < scr->getScriptSize() - 2);
+byte *Script::findBlock(int type) {
+ byte *buf = _buf;
+ bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
- // And now a second pass to adjust objects and class pointers, and the general pointers
- objLength = 0;
- curOffset = oldScriptHeader ? 2 : 0;
+ if (oldScriptHeader)
+ buf += 2;
do {
- objType = scr->getHeap(curOffset);
- if (!objType)
+ int seekerType = READ_LE_UINT16(buf);
+
+ if (seekerType == 0)
break;
+ if (seekerType == type)
+ return buf;
- objLength = scr->getHeap(curOffset + 2);
- curOffset += 4; // skip header
+ int seekerSize = READ_LE_UINT16(buf + 2);
+ assert(seekerSize > 0);
+ buf += seekerSize;
+ } while (1);
- reg_t addr = make_reg(segmentId, curOffset);
+ return NULL;
+}
- 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);
- obj->initSpecies(segMan, addr);
+// memory operations
- if (!obj->initBaseObject(segMan, addr)) {
- warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr));
- scr->scriptObjRemove(addr);
- }
- } // if object or class
- break;
- default:
- break;
- }
+void Script::mcpyInOut(int dst, const void *src, size_t n) {
+ if (_buf) {
+ assert(dst + n <= _bufSize);
+ memcpy(_buf + dst, src, n);
+ }
+}
- curOffset += objLength - 4;
- } while (objType != 0 && curOffset < scr->getScriptSize() - 2);
+bool Script::isValidOffset(uint16 offset) const {
+ return offset < _bufSize;
}
-int script_instantiate(ResourceManager *resMan, SegManager *segMan, int scriptNum) {
- SegmentId segmentId = segMan->getScriptSegment(scriptNum);
- Script *scr = segMan->getScriptIfLoaded(segmentId);
- if (scr) {
- if (!scr->isMarkedAsDeleted()) {
- scr->incrementLockers();
- return segmentId;
+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();
+ }
+
+ 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());
+
+ for (uint16 i = 0; i < getLocalsCount(); i++)
+ locals->_locals[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(base + i * 2));
} else {
- scr->freeScript();
+ // 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;
}
- } else {
- scr = segMan->allocateScript(scriptNum, &segmentId);
}
+}
- scr->init(scriptNum, resMan);
- scr->load(resMan);
-
+void Script::initialiseClasses(SegManager *segMan) {
+ const byte *seeker = 0;
+ uint16 mult = 0;
+
if (getSciVersion() >= SCI_VERSION_1_1) {
- int heapStart = scr->getScriptSize();
- segMan->scriptInitialiseLocals(make_reg(segmentId, heapStart + 4));
- segMan->scriptInitialiseObjectsSci11(segmentId);
- scr->relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(scr->_heapStart)));
+ seeker = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2;
+ mult = 2;
} else {
- script_instantiate_sci0(scr, segmentId, segMan);
- byte *relocationBlock = scr->findBlock(SCI_OBJ_POINTERS);
- if (relocationBlock)
- scr->relocate(make_reg(segmentId, relocationBlock - scr->_buf + 4));
+ seeker = findBlock(SCI_OBJ_CLASS);
+ mult = 1;
}
- return segmentId;
-}
-
-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 = 0;
- Script *scr = segMan->getScript(seg);
+ if (!seeker)
+ return;
- // Make a pass over the object in order uninstantiate all superclasses
+ uint16 marker;
+ bool isClass;
+ uint16 classpos;
+ int16 species = 0;
- do {
- reg.offset += objLength; // Step over the last checked object
+ 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;
- objType = scr->getHeap(reg.offset);
- if (!objType)
+ if (!marker)
break;
- objLength = scr->getHeap(reg.offset + 2); // use SEG_UGET_HEAP ??
- reg.offset += 4; // Step over header
+ 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 ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class?
- int superclass;
+ 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));
+ }
- reg.offset -= SCRIPT_OBJECT_MAGIC_OFFSET;
+ seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * mult;
+ }
+}
- superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass...
+void Script::initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId) {
+ bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
+ const byte *seeker = _buf + (oldScriptHeader ? 2 : 0);
- if (superclass >= 0) {
- int superclass_script = segMan->getClass(superclass).script;
+ do {
+ uint16 objType = READ_SCI11ENDIAN_UINT16(seeker);
+ if (!objType)
+ break;
- 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
+ switch (objType) {
+ case SCI_OBJ_OBJECT:
+ 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);
+ }
}
+ break;
- reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET;
- } // if object or class
+ default:
+ break;
+ }
- reg.offset -= 4; // Step back on header
+ seeker += READ_SCI11ENDIAN_UINT16(seeker + 2);
+ } while ((uint32)(seeker - _buf) < getScriptSize() - 2);
- } while (objType != 0);
+ byte *relocationBlock = findBlock(SCI_OBJ_POINTERS);
+ if (relocationBlock)
+ relocate(make_reg(segmentId, relocationBlock - getBuf() + 4));
}
-void script_uninstantiate(SegManager *segMan, int script_nr) {
- SegmentId segment = segMan->getScriptSegment(script_nr);
- Script *scr = segMan->getScriptIfLoaded(segment);
+void Script::initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId) {
+ const byte *seeker = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2;
- if (!scr) { // Is it already loaded?
- //warning("unloading script 0x%x requested although not loaded", script_nr);
- // This is perfectly valid SCI behaviour
- return;
- }
+ while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) {
+ reg_t reg = make_reg(segmentId, seeker - _buf);
+ Object *obj = scriptObjInit(reg);
- scr->decrementLockers(); // One less locker
+ // Copy base from species class, as we need its selector IDs
+ obj->setSuperClassSelector(
+ segMan->getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG));
- if (scr->getLockers() > 0)
- return;
+ // 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());
+ }
- // Free all classtable references to this script
- for (uint i = 0; i < segMan->classTableSize(); i++)
- if (segMan->getClass(i).reg.segment == segment)
- segMan->setClassOffset(i, 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, _nr));
- if (getSciVersion() < SCI_VERSION_1_1)
- script_uninstantiate_sci0(segMan, script_nr, segment);
- // FIXME: Add proper script uninstantiation for SCI 1.1
+ seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2;
+ }
- if (scr->getLockers())
- return; // if xxx.lockers > 0
+ relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(_heapStart)));
+}
+
+reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) const {
+ addr.offset = 0;
+ return addr;
+}
- // Otherwise unload it completely
- // Explanation: I'm starting to believe that this work is done by SCI itself.
- scr->markDeleted();
+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);
+}
- debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr);
+Common::Array<reg_t> Script::listAllDeallocatable(SegmentId segId) const {
+ const reg_t r = make_reg(segId, 0);
+ return Common::Array<reg_t>(&r, 1);
+}
- 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;
}
+Common::Array<reg_t> Script::listObjectReferences() const {
+ Common::Array<reg_t> tmp;
+
+ // Locals, if present
+ if (_localsSegment)
+ tmp.push_back(make_reg(_localsSegment, 0));
+
+ // 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 tmp;
+}
} // End of namespace Sci
diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h
index e94e9f64e6..3817f8aae1 100644
--- a/engines/sci/engine/script.h
+++ b/engines/sci/engine/script.h
@@ -27,14 +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
-
enum ScriptObjectTypes {
SCI_OBJ_TERMINATOR,
SCI_OBJ_OBJECT,
@@ -49,160 +48,214 @@ 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);
+
+ 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);
+
+ /**
+ * Removes a script object
+ * @param obj_pos Location (segment, offset) of the object.
+ */
+ void scriptObjRemove(reg_t obj_pos);
-extern opcode_format g_opcode_formats[128][4];
+ /**
+ * Initializes the script's local variables
+ * @param segMan A reference to the segment manager
+ */
+ void initialiseLocals(SegManager *segMan);
-void script_adjust_opcode_formats(EngineState *s);
+ /**
+ * 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);
+
+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/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp
index 159c278e8c..9c08526fbb 100644
--- a/engines/sci/engine/scriptdebug.cpp
+++ b/engines/sci/engine/scriptdebug.cpp
@@ -63,15 +63,11 @@ const char *opcodeNames[] = {
"-sli", "-sti", "-spi"
};
-extern const char *selector_name(EngineState *s, int selector);
-
-DebugState g_debugState;
-
// 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;
@@ -84,7 +80,7 @@ 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 = script_entity->getBuf();
scr_size = script_entity->getBufSize();
if (pos.offset >= scr_size) {
@@ -197,7 +193,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
if (!obj)
warning("Attempted to reference on non-object at %04x:%04x", PRINT_REG(s->xs->objp));
else
- printf(" (%s)", selector_name(s, obj->propertyOffsetToId(s->_segMan, scr[pos.offset + 1])));
+ printf(" (%s)", g_sci->getKernel()->getSelectorName(obj->propertyOffsetToId(s->_segMan, scr[pos.offset + 1])).c_str());
}
}
@@ -244,7 +240,7 @@ 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 (lookupSelector(s->_segMan, called_obj_addr, selector, 0, &fun_ref)) {
case kSelectorMethod:
@@ -279,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, s->xs->addr.pc, 0, 1);
- if (s->seeking == kDebugSeekGlobal)
- printf("Global %d (0x%x) = %04x:%04x\n", s->seekSpecial,
- s->seekSpecial, PRINT_REG(s->script_000->_localsBlock->_locals[s->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(s->xs->addr.pc.segment, SEG_TYPE_SCRIPT);
-
- if (mobj) {
- Script *scr = (Script *)mobj;
- byte *code_buf = scr->_buf;
- int code_buf_size = scr->getBufSize();
- int opcode = s->xs->addr.pc.offset >= code_buf_size ? 0 : code_buf[s->xs->addr.pc.offset];
- int op = opcode >> 1;
- int paramb1 = s->xs->addr.pc.offset + 1 >= code_buf_size ? 0 : code_buf[s->xs->addr.pc.offset + 1];
- int paramf1 = (opcode & 1) ? paramb1 : (s->xs->addr.pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + s->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", s->script_step_counter);
+ 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) {
@@ -491,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 4d3e6f754e..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;
@@ -70,10 +71,10 @@ 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();
@@ -81,10 +82,10 @@ void SegManager::resetSegMan() {
}
void SegManager::initSysStrings() {
- sysStrings = (SystemStrings *)allocSegment(new SystemStrings(), &sysStringsSegment);
+ _sysStrings = (SystemStrings *)allocSegment(new SystemStrings(), &_sysStringsSegId);
// Allocate static buffer for savegame and CWD directories
- SystemString *strSaveDir = &sysStrings->_strings[SYS_STRING_SAVEDIR];
+ 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));
@@ -93,23 +94,17 @@ void SegManager::initSysStrings() {
::strcpy(strSaveDir->_value, "");
// Allocate static buffer for the parser base
- SystemString *strParserBase = &sysStrings->_strings[SYS_STRING_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;
@@ -162,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);
}
@@ -173,12 +168,12 @@ int SegManager::deallocate(SegmentId seg, bool recursive) {
return 1;
}
-bool SegManager::isHeapObject(reg_t 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) {
@@ -199,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;
@@ -242,7 +237,7 @@ Object *SegManager::getObject(reg_t pos) {
} else if (mobj->getType() == SEG_TYPE_SCRIPT) {
Script *scr = (Script *)mobj;
if (pos.offset <= scr->getBufSize() && pos.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET
- && RAW_IS_OBJECT(scr->_buf + pos.offset)) {
+ && RAW_IS_OBJECT(scr->getBuf(pos.offset))) {
obj = scr->getObject(pos.offset);
}
}
@@ -268,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;
+
+ reg_t objpos = make_reg(i, 0);
- // It's a script or a clone table, scan all objects in it
- for (; idx < max_index; ++idx) {
- const 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) {
+ 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
@@ -366,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);
@@ -377,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;
@@ -389,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;
}
@@ -408,6 +380,12 @@ DataStack *SegManager::allocateStack(int size, SegmentId *segid) {
retval->_entries = (reg_t *)calloc(size, sizeof(reg_t));
retval->_capacity = size;
+ // 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);
+
return retval;
}
@@ -431,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)
@@ -454,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;
}
@@ -465,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];
- const 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]);
}
@@ -527,58 +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 nodebase;
- Node *n = allocateNode(&nodebase);
+ reg_t nodeRef;
+ Node *n = allocateNode(&nodeRef);
n->pred = n->succ = NULL_REG;
n->key = key;
n->value = value;
- return nodebase;
+ 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;
}
@@ -606,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");
}
@@ -646,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);
}
@@ -695,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()) {
@@ -822,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));
@@ -841,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));
@@ -867,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);
@@ -887,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
@@ -901,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]);
}
@@ -941,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]);
}
@@ -979,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 9312f51f9d..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,6 +117,30 @@ public:
*/
SegmentId getScriptSegment(int script_nr, ScriptLoadType load);
+ /**
+ * 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);
@@ -131,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
@@ -223,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
@@ -265,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
@@ -378,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).
*/
@@ -429,22 +438,27 @@ public:
*/
reg_t findObjectByName(const Common::String &name, int index = -1);
- void scriptInitialiseObjectsSci11(SegmentId seg);
-
- uint32 classTableSize() { return _classTable.size(); }
- Class getClass(int index) { return _classTable[index]; }
+ 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); }
/**
* Obtains the system strings segment ID
*/
- SegmentId getSysStringsSegment() { return sysStringsSegment; }
+ SegmentId getSysStringsSegment() { return _sysStringsSegId; }
-public: // TODO: make private
- Common::Array<SegmentObj *> _heap;
- // Only accessible from saveLoadWithSerializer()
- Common::Array<Class> _classTable; /**< Table of all classes */
+ /**
+ * 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);
@@ -453,35 +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 sysStringsSegment;
-public: // TODO: make private. Only kString() needs direct access
- SystemStrings *sysStrings;
-
-private:
+ 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();
@@ -494,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 0e0a759d4b..cb908979a3 100644
--- a/engines/sci/engine/segment.cpp
+++ b/engines/sci/engine/segment.cpp
@@ -86,175 +86,52 @@ 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;
-
- _markedAsDeleted = false;
-}
-
-Script::~Script() {
- freeScript();
-}
-
-void Script::freeScript() {
- free(_buf);
- _buf = NULL;
- _bufSize = 0;
-
- _objects.clear();
- _codeBlocks.clear();
-}
-
-void Script::init(int script_nr, ResourceManager *resMan) {
- Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0);
-
- _localsOffset = 0;
- _localsBlock = NULL;
-
- _codeBlocks.clear();
-
- _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 (_bufSize > 65535)
- error("Script and heap sizes combined exceed 64K. This means a fundamental "
- "design bug was made regarding SCI1.1 and newer games.\nPlease "
- "report this error to the ScummVM team");
- }
-}
-
-void Script::load(ResourceManager *resMan) {
- Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0);
- assert(script != 0);
-
- _buf = (byte *)malloc(_bufSize);
- assert(_buf);
-
- assert(_bufSize >= script->size);
- memcpy(_buf, script->data, script->size);
-
- if (getSciVersion() >= SCI_VERSION_1_1) {
- Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0);
- assert(heap != 0);
-
- _heapStart = _buf + _scriptSize;
-
- assert(_bufSize - _scriptSize <= heap->size);
- memcpy(_heapStart, heap->data, heap->size);
- }
-
- _codeBlocks.clear();
-
- _exportTable = 0;
- _numExports = 0;
- _synonyms = 0;
- _numSynonyms = 0;
-
- if (getSciVersion() >= SCI_VERSION_1_1) {
- if (READ_LE_UINT16(_buf + 1 + 5) > 0) {
- _exportTable = (const uint16 *)(_buf + 1 + 5 + 2);
- _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1);
- }
- } else {
- _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 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;
}
-}
-
-Object *Script::allocateObject(uint16 offset) {
- return &_objects[offset];
-}
-
-Object *Script::getObject(uint16 offset) {
- if (_objects.contains(offset))
- return &_objects[offset];
- else
- return 0;
-}
-
-const Object *Script::getObject(uint16 offset) const {
- if (_objects.contains(offset))
- return &_objects[offset];
- else
- return 0;
-}
-
-Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) {
- Object *obj;
-
- if (getSciVersion() < SCI_VERSION_1_1 && fullObjectInit)
- obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET)
-
- VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n");
-
- obj = allocateObject(obj_pos.offset);
-
- VERIFY(obj_pos.offset + kOffsetFunctionArea < (int)_bufSize, "Function area pointer stored beyond end of script\n");
-
- obj->init(_buf, obj_pos, fullObjectInit);
-
- return obj;
-}
-
-void Script::scriptObjRemove(reg_t obj_pos) {
- if (getSciVersion() < SCI_VERSION_1_1)
- obj_pos.offset += 8;
-
- _objects.erase(obj_pos.toUint16());
+ return NULL;
}
// 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;
@@ -267,7 +144,7 @@ static bool relocateBlock(Common::Array<reg_t> &block, int block_location, Segme
return false;
if (rel & 1) {
- warning("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location);
+ error("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location);
return false;
}
block[idx].segment = segment; // Perform relocation
@@ -277,182 +154,12 @@ static bool relocateBlock(Common::Array<reg_t> &block, int block_location, Segme
return true;
}
-bool Script::relocateLocal(SegmentId segment, int location) {
- if (_localsBlock)
- return relocateBlock(_localsBlock->_locals, _localsOffset, segment, location, _scriptSize);
- else
- return false;
-}
-
-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::relocate(reg_t block) {
- byte *heap = _buf;
- uint16 heapSize = (uint16)_bufSize;
- uint16 heapOffset = 0;
-
- if (getSciVersion() >= SCI_VERSION_1_1) {
- heap = _heapStart;
- heapSize = (uint16)_heapSize;
- heapOffset = _scriptSize;
- }
-
- 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;
-
- for (int i = 0; i < count; i++) {
- int pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset;
- // This occurs in SCI01/SCI1 games where every 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");
- }
-
- 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 (it->_value.relocate(block.segment, pos, _scriptSize))
- done = true;
- }
-
- // Sanity check for SCI0-SCI1
- if (getSciVersion() < SCI_VERSION_1_1) {
- 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) {
- debug("While processing relocation block %04x:%04x:\n", PRINT_REG(block));
- debug("Relocation failed for index %04x (%d/%d)\n", pos, exportIndex + 1, count);
- if (_localsBlock)
- debug("- locals: %d at %04x\n", _localsBlock->_locals.size(), _localsOffset);
- else
- debug("- No locals\n");
- for (it = _objects.begin(), k = 0; it != end; ++it, ++k)
- debug("- obj#%d at %04x w/ %d vars\n", k, it->_value.getPos().offset, it->_value.getVarCount());
- debug("Trying to continue anyway...\n");
- }
- }
-
- exportIndex++;
- }
-}
-
-void Script::incrementLockers() {
- _lockers++;
-}
-
-void Script::decrementLockers() {
- if (_lockers > 0)
- _lockers--;
-}
-
-int Script::getLockers() const {
- return _lockers;
-}
-
-void Script::setLockers(int lockers) {
- _lockers = lockers;
-}
-
-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(_exportTable + pubfunct);
- VERIFY(offset < _bufSize, "invalid export function pointer");
-
- return offset;
-}
-
-byte *Script::findBlock(int type) {
- byte *buf = _buf;
- bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
-
- if (oldScriptHeader)
- buf += 2;
-
- do {
- int seekerType = READ_LE_UINT16(buf);
-
- if (seekerType == 0)
- break;
- if (seekerType == type)
- return buf;
-
- int seekerSize = READ_LE_UINT16(buf + 2);
- assert(seekerSize > 0);
- buf += seekerSize;
- } while (1);
-
- return NULL;
-}
-
-
-// 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);
-}
-
SegmentRef SegmentObj::dereference(reg_t pointer) {
error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment",
PRINT_REG(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;
@@ -471,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;
@@ -518,58 +234,21 @@ 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) const {
- 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) const {
- (*note)(param, make_reg(segId, 0));
-}
-
-void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const {
- 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)
- (*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) const {
+Common::Array<reg_t> CloneTable::listAllOutgoingReferences(reg_t addr) const {
+ Common::Array<reg_t> tmp;
// assert(addr.segment == _segId);
if (!isValidEntry(addr.offset)) {
@@ -580,20 +259,20 @@ void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback
// 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));
@@ -620,11 +299,14 @@ reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) const {
return make_reg(owner_seg, 0);
}
-void LocalVariables::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const {
+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;
}
@@ -634,11 +316,14 @@ reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) const {
return addr;
}
-void DataStack::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const {
+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;
}
@@ -647,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) const {
+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));
}
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;
}
@@ -667,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) const {
+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));
}
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;
}
@@ -743,7 +432,7 @@ int Object::propertyOffsetToId(SegManager *segMan, int propertyOffset) const {
int selectors = getVarCount();
if (propertyOffset < 0 || (propertyOffset >> 1) >= selectors) {
- warning("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d])",
+ error("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d])",
propertyOffset, propertyOffset >> 1, selectors - 1);
return -1;
}
@@ -800,8 +489,9 @@ reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) const {
return addr;
}
-void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const {
- (*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
@@ -819,10 +509,10 @@ void ArrayTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) {
freeEntry(sub_addr.offset);
}
-void ArrayTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const {
+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));
}
const SciArray<reg_t> *array = &(_table[addr.offset]);
@@ -830,8 +520,10 @@ void ArrayTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback
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() const {
diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h
index f1b6dccaa2..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,6 +105,7 @@ 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.
@@ -116,30 +116,33 @@ public:
/**
* 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) const {}
+ 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) const {}
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const {
+ return Common::Array<reg_t>();
+ }
};
-
-struct IntMapper;
-
enum {
SYS_STRINGS_MAX = 4,
@@ -195,7 +198,7 @@ public:
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 listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const;
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -331,199 +334,6 @@ private:
reg_t _pos; /**< Object offset within its script; for clones, this is their base */
};
-struct CodeBlock {
- reg_t pos;
- int size;
-};
-
-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 */
- byte *_heapStart; /**< Start of heap if SCI1.1, NULL otherwise */
-
- uint32 getScriptSize() { return _scriptSize; }
- uint32 getHeapSize() { return _heapSize; }
- uint32 getBufSize() { return _bufSize; }
-
-protected:
- int _lockers; /**< Number of classes and objects that require this script */
-
-private:
- size_t _scriptSize;
- size_t _heapSize;
- size_t _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 */
-
- Common::Array<CodeBlock> _codeBlocks;
-
-public:
- /**
- * Table for objects, contains property variables.
- * Indexed by the TODO offset.
- */
- ObjMap _objects;
-
- int _localsOffset;
- SegmentId _localsSegment; /**< The local variable segment */
- LocalVariables *_localsBlock;
-
- bool _markedAsDeleted;
-
-public:
- Script();
- ~Script();
-
- void freeScript();
- void init(int script_nr, ResourceManager *resMan);
- void load(ResourceManager *resMan);
-
- 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 void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const;
- virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const;
-
- virtual void saveLoadWithSerializer(Common::Serializer &ser);
-
- Object *allocateObject(uint16 offset);
- Object *getObject(uint16 offset);
- const Object *getObject(uint16 offset) const;
-
- /**
- * 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, bool fullObjectInit = true);
-
- /**
- * 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 relocate(reg_t block);
-
-private:
- bool relocateLocal(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;
-
- /** 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);
-
-
- /**
- * 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;
-
- /**
- * Finds the pointer where a block of a specific type starts from
- */
- byte *findBlock(int type);
-};
-
/** Data stack */
struct DataStack : SegmentObj {
int _capacity; /**< Number of stack entries */
@@ -542,7 +352,7 @@ public:
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 listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const;
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -630,10 +440,12 @@ public:
entries_used--;
}
- virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const {
+ 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;
}
};
@@ -643,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) const;
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -654,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) const;
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -665,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) const;
+ virtual Common::Array<reg_t> listAllOutgoingReferences(reg_t object) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -678,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);
@@ -701,7 +516,7 @@ public:
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 listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const;
+ virtual Common::Array<reg_t> listAllDeallocatable(SegmentId segId) const;
virtual void saveLoadWithSerializer(Common::Serializer &ser);
};
@@ -811,6 +626,7 @@ public:
byte getType() const { return _type; }
uint32 getSize() const { return _size; }
T *getRawData() { return _data; }
+ const T *getRawData() const { return _data; }
protected:
int8 _type;
@@ -834,7 +650,7 @@ 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) const;
+ 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 04a1b8fbba..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);
@@ -157,7 +160,11 @@ void Kernel::mapSelectors() {
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,6 +179,13 @@ 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
}
@@ -188,42 +202,37 @@ void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t
ObjVarRef address;
if ((selectorId < 0) || (selectorId > (int)g_sci->getKernel()->getSelectorNamesSize())) {
- warning("Attempt to write to invalid selector %d of"
+ error("Attempt to write to invalid selector %d of"
" object at %04x:%04x.", selectorId, PRINT_REG(object));
return;
}
if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable)
- warning("Selector '%s' of object at %04x:%04x could not be"
+ 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 invokeSelectorArgv(EngineState *s, reg_t object, int selectorId, 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, selectorId); // The selector we want to call
stackframe[1] = make_reg(0, argc); // Argument count
- slc_type = lookupSelector(s->_segMan, object, selectorId, 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",
+ error("Selector '%s' of object at %04x:%04x could not be invoked",
g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object));
- if (noinvalid == kStopOnInvalidSelector)
- error("[Kernel] Not recoverable: VM was halted");
- return 1;
}
if (slc_type == kSelectorVariable) {
- warning("Attempting to invoke variable selector %s of object %04x:%04x",
+ error("Attempting to invoke variable selector %s of object %04x:%04x",
g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object));
- return 0;
}
for (i = 0; i < argc; i++)
@@ -237,25 +246,7 @@ int invokeSelectorArgv(EngineState *s, reg_t object, int selectorId, SelectorInv
xstack->sp += argc + 2;
xstack->fp += argc + 2;
- run_vm(s, false); // Start a new vm
-
- return 0;
-}
-
-int invokeSelector(EngineState *s, reg_t object, int selectorId, 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 = invokeSelectorArgv(s, object, selectorId, noinvalid, k_argc, k_argp, argc, args);
-
- delete[] args;
- return retval;
+ run_vm(s); // Start a new vm
}
SelectorType lookupSelector(SegManager *segMan, reg_t obj_location, Selector selectorId, ObjVarRef *varp, reg_t *fptr) {
diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h
index f50b9ab1b3..00e795c1b9 100644
--- a/engines/sci/engine/selector.h
+++ b/engines/sci/engine/selector.h
@@ -30,13 +30,127 @@
#include "sci/engine/vm_types.h" // for reg_t
#include "sci/engine/vm.h"
-#include "sci/engine/kernel.h" // for Kernel::_selectorCache
namespace Sci {
-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
};
/**
@@ -71,18 +185,8 @@ void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t
/**
* Invokes a selector from an object.
*/
-int invokeSelector(EngineState *s, reg_t object, int selectorId, SelectorInvocation noinvalid,
- int k_argc, StackPtr k_argp, int argc, ...);
-int invokeSelectorArgv(EngineState *s, reg_t object, int selectorId, SelectorInvocation noinvalid,
- int k_argc, StackPtr k_argp, int argc, const reg_t *argv);
-
-/**
- * Kludge for use with invokeSelector(). Used for compatibility with compilers
- * that cannot handle vararg macros.
- */
-#define INV_SEL(s, _object_, _selector_, _noinvalid_) \
- s, _object_, g_sci->getKernel()->_selectorCache._selector_, _noinvalid_, argc, 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 b4a04f8826..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"
@@ -80,73 +81,91 @@ EngineState::~EngineState() {
}
void EngineState::reset(bool isRestoring) {
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- sfx_init_flags = 0;
-#endif
-
if (!isRestoring) {
- script_000 = 0;
- _gameObj = NULL_REG;
-
_memorySegmentSize = 0;
- _soundCmd = 0;
- restarting_flags = 0;
+ _fileHandles.resize(5);
- execution_stack_base = 0;
- _executionStackPosChanged = false;
+ abortScriptProcessing = kAbortNone;
+ }
- _fileHandles.resize(5);
+ executionStackBase = 0;
+ _executionStackPosChanged = false;
+ stack_base = 0;
+ stack_top = 0;
- r_acc = NULL_REG;
- restAdjust = 0;
- r_prev = NULL_REG;
+ restAdjust = 0;
- stack_base = 0;
- stack_top = 0;
- }
+ r_acc = NULL_REG;
+ r_prev = NULL_REG;
- last_wait_time = 0;
+ lastWaitTime = 0;
- gc_countdown = 0;
+ gcCountDown = 0;
_throttleCounter = 0;
_throttleLastTime = 0;
_throttleTrigger = false;
- script_abort_flag = 0;
- script_step_counter = 0;
- script_gc_interval = GC_INTERVAL;
+ _lastSaveVirtualId = SAVEGAMEID_OFFICIALRANGE_START;
+ _lastSaveNewId = 0;
- restoring = false;
+ scriptStepCounter = 0;
+ scriptGCInterval = GC_INTERVAL;
}
-void EngineState::wait(int16 ticks) {
- uint32 time;
+void EngineState::speedThrottler(uint32 neededSleep) {
+ if (_throttleTrigger) {
+ uint32 curTime = g_system->getMillis();
+ uint32 duration = curTime - _throttleLastTime;
- time = g_system->getMillis();
- r_acc = make_reg(0, ((long)time - (long)last_wait_time) * 60 / 1000);
- last_wait_time = time;
+ if (duration < neededSleep) {
+ g_sci->sleep(neededSleep - duration);
+ _throttleLastTime = g_system->getMillis();
+ } else {
+ _throttleLastTime = curTime;
+ }
+ _throttleTrigger = false;
+ }
+}
+
+void EngineState::wait(int16 ticks) {
+ 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() {
- uint size = execution_stack_base + 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());
+ 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) {
@@ -204,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;
@@ -231,8 +250,8 @@ kLanguage SciEngine::getSciLanguage() {
lang = K_LANG_ENGLISH;
- if (_kernel->_selectorCache.printLang != -1) {
- lang = (kLanguage)readSelectorValue(_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.
@@ -265,21 +284,27 @@ kLanguage SciEngine::getSciLanguage() {
default:
lang = K_LANG_ENGLISH;
}
-
- // Store language in printLang selector
- writeSelectorValue(_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)readSelectorValue(_gamestate->_segMan, _gamestate->_gameObj, SELECTOR(subtitleLang));
+ if (SELECTOR(subtitleLang) != -1) {
+ subLang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(subtitleLang));
}
kLanguage secondLang;
@@ -299,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 68e6a5516a..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,11 +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
+ 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 {
@@ -105,19 +119,11 @@ public:
/* 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 */
@@ -130,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 */
@@ -138,11 +147,11 @@ 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 */
@@ -151,35 +160,31 @@ public:
// Script state
ExecStack *xs;
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
-
- Script *script_000; /**< script 000, e.g. for globals */
+ 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
- int loadFromLauncher;
+ AbortGameState abortScriptProcessing;
+ int16 gameIsRestarting; // is set when restarting (=1) or restoring the game (=2)
- /**
- * 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.
- */
- int script_abort_flag; // Set to 1 to abort execution. Set to 2 to force a replay afterwards
- int script_step_counter; // Counts the number of steps executed
- int script_gc_interval; // Number of steps in between gcs
+ int scriptStepCounter; // Counts the number of steps executed
+ int scriptGCInterval; // Number of steps in between gcs
uint16 currentRoomNumber() const;
void setRoomNumber(uint16 roomNumber);
/**
+ * Sets global variables from script 0
+ */
+ void initGlobals();
+
+ /**
* Shrink execution stack to size.
- * Contains an assert it is not already smaller.
+ * Contains an assert if it is not already smaller.
*/
void shrinkStackToBase();
- reg_t _gameObj; /**< Pointer to the game object */
-
- int gc_countdown; /**< Number of kernel calls until next gc */
+ int gcCountDown; /**< Number of kernel calls until next gc */
public:
MessageState *_msgState;
@@ -196,8 +201,6 @@ public:
* Resets the engine state.
*/
void reset(bool isRestoring);
-
- bool restoring; /**< A flag to indicate if a game is being restored */
};
} // 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 b04cc473b5..35fc3ca566 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -30,20 +30,21 @@
#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
#define SCI_XS_CALLEE_LOCALS ((SegmentId)-1)
@@ -59,6 +60,8 @@ const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET};
* @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
@@ -69,7 +72,7 @@ const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET};
* @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);
@@ -94,20 +97,24 @@ static ExecStack *add_exec_stack_varselector(Common::List<ExecStack> &execStack,
// 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;
+ // FIXME/TODO: Where does this occur? Returning a dummy reg here could lead
+ // to all sorts of issues! Turned it into an error for now...
+ // 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) {
- debugC(2, kDebugLevelVM, "[VM] Sending to disposed object!");
- return dummyReg;
+ error("validate_property: Sending to disposed object");
+ //return dummyReg;
}
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;
@@ -127,7 +134,10 @@ 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. Check
+ // callKernelFunc() below
+ error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]. Address: %04x:%04x", reg.segment, PRINT_REG(reg));
return 0;
}
@@ -135,15 +145,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) {
@@ -158,10 +163,15 @@ 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 {
+ // WORKAROUND: Mixed-Up Mother Goose tries to use an invalid parameter in Event::new().
+ // Just skip around it here so we don't error out in validate_arithmetic.
+ if (g_sci->getGameId() == GID_MOTHERGOOSE && type == VAR_PARAM && index == 1)
+ return false;
+
debugC(2, kDebugLevelVM, "%s", txt.c_str());
debugC(2, kDebugLevelVM, "[VM] Access within stack boundaries; access granted.");
return true;
@@ -173,15 +183,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.
@@ -200,59 +262,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 (lookupSelector(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(s->variables[type], s->stack_base, type, s->variables_max[type], index, __LINE__, def)
-#define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->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, (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);
}
@@ -270,24 +339,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;
+ g_sci->checkExportBreakpoint(script, pubfunct);
- 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;
- }
- }
- }
-
- 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);
}
@@ -297,7 +351,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?
@@ -325,6 +379,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
@@ -349,27 +427,7 @@ 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));
- printSendActions = true;
- 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());
@@ -405,19 +463,18 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
}
if (argc > 1) {
- // argc can indeed be bigger than 1 in some cases, and it seems correct
- // (i.e. we should skip that many bytes later on)... question is, why
- // does this occur? Could such calls be used to point to data after X
- // bytes in the heap? What are the skipped bytes in this case?
- // In SQ4CD, this occurs with the returnVal selector of object
- // Sq4GlobalNarrator when the game starts, and right after the narrator
- // is heard (e.g. after he talks when examining something)
+ // 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];
- warning("send_selector(): argc = %d while modifying variable selector "
- "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x",
- argc, selector, g_sci->getKernel()->getSelectorName(selector).c_str(), PRINT_REG(send_obj),
- s->_segMan->getObjectName(send_obj), PRINT_REG(oldReg), PRINT_REG(newReg));
+ 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));
}
{
@@ -444,7 +501,28 @@ 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 (printSendActions) {
- debug("[invoke selector]\n");
+ 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;
}
@@ -477,7 +555,7 @@ 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);
@@ -486,7 +564,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt
}
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;
@@ -496,7 +574,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
@@ -520,8 +598,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
@@ -529,10 +609,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);
@@ -560,84 +636,187 @@ static reg_t pointer_add(EngineState *s, reg_t base, int offset) {
}
}
-static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) {
+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 (kernelFuncNum >= (int)g_sci->getKernel()->_kernelFuncs.size())
- error("Invalid kernel function 0x%x requested", 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);
+}
- const KernelFuncWithSignature &kernelFunc = g_sci->getKernel()->_kernelFuncs[kernelFuncNum];
+static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) {
+ Kernel *kernel = g_sci->getKernel();
- if (kernelFunc.signature
- && !g_sci->getKernel()->signatureMatch(kernelFunc.signature, argc, s->xs->sp + 1)) {
- error("[VM] Invalid arguments to kernel call %x", kernelFuncNum);
- }
+ 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 (!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.1 equivalent
- if (s->loadFromLauncher >= 0 && (
- (kernelFuncNum == 0x8 && getSciVersion() <= SCI_VERSION_1_1) || // DrawPic
- (kernelFuncNum == 0x3d && getSciVersion() == SCI_VERSION_2) // GetSaveDir
- //(kernelFuncNum == 0x28 && getSciVersion() == SCI_VERSION_2_1) // AddPlane
- )) {
-
- // A game is being loaded from the launcher, and the game is about to draw something on
- // screen, hence all initialization has taken place (i.e. menus have been constructed etc).
- // Therefore, inject a kRestoreGame call here, instead of the requested function.
- // The restore call is injected here mainly for games which have a menu, as the menu is
- // constructed when the game starts and is not reconstructed when a saved game is loaded.
- int saveSlot = s->loadFromLauncher;
- s->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);
+ 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 = s->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)
@@ -706,53 +885,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
- s->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:
s->xs = &(s->_executionStack.back());
ExecStack *xs_new = NULL;
Object *obj = s->_segMan->getObject(s->xs->objp);
+ Script *scr = 0;
Script *local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment);
- int old_execution_stack_base = s->execution_stack_base;
+ 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)
- s->variables_max[VAR_GLOBAL] = s->script_000->_localsBlock->_locals.size();
- else
- s->variables_max[VAR_GLOBAL] = 0;
-#endif
-
- s->variables_seg[VAR_GLOBAL] = s->script_000->_localsSegment;
- s->variables_seg[VAR_TEMP] = s->variables_seg[VAR_PARAM] = s->_segMan->findSegmentByType(SEG_TYPE_STACK);
- s->variables_base[VAR_TEMP] = s->variables_base[VAR_PARAM] = s->stack_base;
-
- // SCI code reads the zeroth argument to determine argc
- if (s->script_000->_localsBlock)
- s->variables_base[VAR_GLOBAL] = s->variables[VAR_GLOBAL] = s->script_000->_localsBlock->_locals.begin();
- else
- s->variables_base[VAR_GLOBAL] = s->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
@@ -760,101 +917,89 @@ void run_vm(EngineState *s, bool restoring) {
int var_type; // See description below
int var_number;
- g_debugState.old_pc_offset = s->xs->addr.pc.offset;
- g_debugState.old_sp = s->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;
+ 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(s->xs->addr.pc.segment);
- if (!scr) {
- // No script? Implicit return via fake instruction buffer
- warning("Running on non-existant script in segment %x", s->xs->addr.pc.segment);
- code_buf = _fake_return_buffer;
-#ifndef DISABLE_VALIDATIONS
- code_buf_size = 2;
-#endif
- s->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(s->xs->objp);
- code_buf = scr->_buf;
-#ifndef DISABLE_VALIDATIONS
- code_buf_size = scr->getBufSize();
-#endif
- local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment);
- if (!local_script) {
- warning("Could not find local script from segment %x", s->xs->local_segment);
- local_script = NULL;
- s->variables_base[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL;
-#ifndef DISABLE_VALIDATIONS
- s->variables_max[VAR_LOCAL] = 0;
-#endif
- } else {
-
- s->variables_seg[VAR_LOCAL] = local_script->_localsSegment;
- if (local_script->_localsBlock)
- s->variables_base[VAR_LOCAL] = s->variables[VAR_LOCAL] = local_script->_localsBlock->_locals.begin();
- else
- s->variables_base[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL;
-#ifndef DISABLE_VALIDATIONS
- if (local_script->_localsBlock)
- s->variables_max[VAR_LOCAL] = local_script->_localsBlock->_locals.size();
- else
- s->variables_max[VAR_LOCAL] = 0;
- s->variables_max[VAR_TEMP] = s->xs->sp - s->xs->fp;
- s->variables_max[VAR_PARAM] = s->xs->argc + 1;
-#endif
- }
- s->variables[VAR_TEMP] = s->xs->fp;
- s->variables[VAR_PARAM] = s->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 (s->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 (s->xs->sp < s->xs->fp)
- error("run_vm(): stack underflow, sp: %04x:%04x, fp: %04x:%04x",
+ error("run_vm(): stack underflow, sp: %04x:%04x, fp: %04x:%04x",
PRINT_REG(*s->xs->sp), PRINT_REG(*s->xs->fp));
- s->variables_max[VAR_TEMP] = s->xs->sp - s->xs->fp;
+ s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp;
- if (s->xs->addr.pc.offset >= code_buf_size)
- error("run_vm(): program counter gone astray, addr: %d, code buffer size: %d",
- s->xs->addr.pc.offset, code_buf_size);
-#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;
- s->xs->addr.pc.offset += readPMachineInstruction(code_buf + s->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;
@@ -908,45 +1053,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)
- ACC_AUX_LOAD();
- aux_acc = aux_acc != 0 ? ((int16)POP()) % aux_acc : 0;
- ACC_AUX_STORE();
+ case op_mod: { // 0x05 (05)
+ r_temp = POP32();
+
+ if (getSciVersion() <= SCI_VERSION_0_LATE) {
+ uint16 modulo, value;
+ if (validate_unsignedInteger(s->r_acc, modulo) && validate_unsignedInteger(r_temp, value))
+ s->r_acc = make_reg(0, (modulo != 0 ? value % modulo : 0));
+ else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, r_temp);
+ } else {
+ // In Iceman (and perhaps from SCI0 0.000.685 onwards in general),
+ // handling for negative numbers was added. Since Iceman doesn't
+ // seem to have issues with the older code, we exclude it for now
+ // for simplicity's sake and use the new code for SCI01 and newer
+ // games. Fixes the battlecruiser mini game in SQ5 (room 850),
+ // bug #3035755
+ int16 modulo, value, result;
+ if (validate_signedInteger(s->r_acc, modulo) && validate_signedInteger(r_temp, value)) {
+ modulo = ABS(modulo);
+ result = (modulo != 0 ? value % modulo : 0);
+ if (result < 0)
+ result += modulo;
+ s->r_acc = make_reg(0, result);
+ } else
+ s->r_acc = arithmetic_lookForWorkaround(opcode, NULL, s->r_acc, r_temp);
+ }
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, NULL, 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));
@@ -954,6 +1169,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);
@@ -961,6 +1177,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);
@@ -968,6 +1185,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) {
@@ -975,44 +1193,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, NULL, r_temp, s->r_acc);
+ }
break;
case op_ugt_: // 0x13 (19)
+ // > (unsigned)
s->r_prev = s->r_acc;
r_temp = POP32();
@@ -1024,17 +1278,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();
@@ -1043,24 +1303,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();
@@ -1069,16 +1342,23 @@ 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)
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))
s->xs->addr.pc.offset += opparams[0];
break;
@@ -1088,43 +1368,54 @@ void run_vm(EngineState *s, bool restoring) {
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)
+ // TOS (Top Of Stack) subtract
s->xs->sp--;
break;
case op_dup: // 0x1e (30)
+ // 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++)
- s->xs->sp[i] = NULL_REG;
+ 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 + 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,
- s->xs->addr.pc.offset + opparams[0]),
+ localCallOffset),
s->xs->sp, s->xs->objp,
(validate_arithmetic(*call_base)) + s->restAdjust,
- call_base, NULL_SELECTOR, s->xs->objp,
+ 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;
@@ -1134,15 +1425,14 @@ void run_vm(EngineState *s, bool restoring) {
}
case op_callk: { // 0x21 (33)
- gc_countdown(s);
+ // Call kernel function
+ gcCountDown(s);
s->xs->sp -= (opparams[1] >> 1) + 1;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
- if (!oldScriptHeader) {
+ if (!oldScriptHeader)
s->xs->sp -= s->restAdjust;
- s->restAdjust = 0; // We just used up the s->restAdjust, remember?
- }
int argc = validate_arithmetic(s->xs->sp[0]);
@@ -1152,17 +1442,23 @@ void run_vm(EngineState *s, bool restoring) {
callKernelFunc(s, opparams[0], argc);
if (!oldScriptHeader)
- s->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)
+ // Call base script
temp = ((opparams[1] >> 1) + s->restAdjust + 1);
s_temp = s->xs->sp;
s->xs->sp -= temp;
@@ -1176,6 +1472,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_calle: // 0x23 (35)
+ // Call external script
temp = ((opparams[2] >> 1) + s->restAdjust + 1);
s_temp = s->xs->sp;
s->xs->sp -= temp;
@@ -1190,18 +1487,18 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_ret: // 0x24 (36)
+ // Return from an execution loop started by call, calle, callb, send, self or super
do {
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 = s->restAdjust; // Update &rest
return; // "Hard" return
}
@@ -1233,6 +1530,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_send: // 0x25 (37)
+ // Send for one or more selectors
s_temp = s->xs->sp;
s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack
@@ -1253,6 +1551,7 @@ 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,
s->xs->addr.pc);
break;
@@ -1262,6 +1561,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_self: // 0x2a (42)
+ // Send to self
s_temp = s->xs->sp;
s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack
@@ -1277,6 +1577,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_super: // 0x2b (43)
+ // Send to any class
r_temp = s->_segMan->getClassAddress(opparams[0], SCRIPT_GET_LOAD, s->xs->addr.pc);
if (!r_temp.segment)
@@ -1299,6 +1600,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_rest: // 0x2c (44)
+ // Pushes all or part of the parameter variable list on the stack
temp = (uint16) opparams[0]; // First argument
s->restAdjust = MAX<int16>(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't
@@ -1308,12 +1610,13 @@ void run_vm(EngineState *s, bool restoring) {
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 = s->variables_seg[var_number];
- r_temp.offset = s->variables[var_number] - s->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);
@@ -1326,6 +1629,7 @@ void run_vm(EngineState *s, bool restoring) {
case op_selfID: // 0x2e (46)
+ // Get 'self' identity
s->r_acc = s->xs->objp;
break;
@@ -1334,66 +1638,83 @@ 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)
+ // Load Offset to Accumulator
s->r_acc.segment = s->xs->addr.pc.segment;
switch (g_sci->_features->detectLofsType()) {
@@ -1407,15 +1728,14 @@ void run_vm(EngineState *s, bool restoring) {
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)
+ // Load Offset to Stack
r_temp.segment = s->xs->addr.pc.segment;
switch (g_sci->_features->detectLofsType()) {
@@ -1429,12 +1749,10 @@ void run_vm(EngineState *s, bool restoring) {
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;
@@ -1455,6 +1773,7 @@ void run_vm(EngineState *s, bool restoring) {
PUSH32(s->xs->objp);
} else {
// Debug opcode op_file, skip null-terminated string (file name)
+ const byte *code_buf = scr->getBuf();
while (code_buf[s->xs->addr.pc.offset++]) ;
}
break;
@@ -1467,42 +1786,49 @@ 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)
+ // 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));
+ 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);
@@ -1512,6 +1838,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());
@@ -1521,6 +1848,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...
@@ -1534,6 +1864,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());
@@ -1543,9 +1875,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);
@@ -1558,9 +1892,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);
@@ -1574,9 +1910,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);
@@ -1589,9 +1927,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);
@@ -1605,9 +1945,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);
@@ -1620,9 +1962,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);
@@ -1636,9 +1980,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);
@@ -1651,9 +1997,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);
@@ -1671,98 +2019,13 @@ void run_vm(EngineState *s, bool restoring) {
if (s->_executionStackPosChanged) // Force initialization
s->xs = xs_new;
-//#ifndef DISABLE_VALIDATIONS
if (s->xs != &(s->_executionStack.back())) {
- warning("xs is stale (%p vs %p); last command was %02x",
+ error("xs is stale (%p vs %p); last command was %02x",
(void *)s->xs, (void *)&(s->_executionStack.back()),
opcode);
}
-//#endif
- ++s->script_step_counter;
- }
-}
-
-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) {
- bool restoring = false;
-
- if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup))
- g_sci->getSciDebugger()->attach();
-
- do {
- s->_executionStackPosChanged = false;
- run_vm(s, restoring);
- if (s->restarting_flags & SCI_GAME_IS_RESTARTING_NOW) { // Restart was requested?
- restoring = false;
- 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);
-
- s->script_abort_flag = 0;
- s->restarting_flags = SCI_GAME_WAS_RESTARTED;
-
- } else {
- restoring = s->restoring;
- if (restoring) {
- game_exit(s);
- s->restoring = false;
- if (s->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);
- }
-
- s->script_abort_flag = 0;
-
- } else
- break; // exit loop
- }
- } while (true);
-
- return s;
-}
-
-int game_run(EngineState **_s) {
- EngineState *s = *_s;
-
- debugC(2, kDebugLevelVM, "Calling %s::play()", g_sci->getGameID());
- _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;
+ ++s->scriptStepCounter;
}
- // and ENGAGE!
- _game_run(*_s);
-
- debugC(2, kDebugLevelVM, "Game::play() finished.");
-
- return 0;
-}
-
-void quit_vm(EngineState *s) {
- s->script_abort_flag = 1; // Terminate VM
- g_debugState.seeking = kDebugSeekNothing;
- g_debugState.runningStep = 0;
}
reg_t *ObjVarRef::getPointer(SegManager *segMan) const {
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index 67a6bd0dc3..ee22e03310 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -49,11 +49,6 @@ class ResourceManager;
/** 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)
-
/** Stack pointer value: Use predecessor's value */
#define CALL_SP_CARRY NULL
@@ -69,115 +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
-
- // SCI1.1 Mac icon bar selectors
- Selector iconIndex; ///< Used to index icon bar objects
-
-#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
@@ -210,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;
@@ -229,6 +118,160 @@ enum {
GC_INTERVAL = 32768
};
+// 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
+};
+
+extern opcode_format g_opcode_formats[128][4];
+
+void script_adjust_opcode_formats();
/**
* Executes function pubfunct of the specified script.
@@ -272,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
@@ -283,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
@@ -314,95 +348,6 @@ 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(EngineState *s);
-
-/**
* 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..e153fadca5
--- /dev/null
+++ b/engines/sci/engine/workarounds.cpp
@@ -0,0 +1,426 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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 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 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, 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_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 the second brother is about to enter the house (where you have to hide in the wardrobe), bug #3039891, temps 1 and 2
+ { 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_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
+ 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, 740, 752, 0, "throwDazzle", "changeState", -1, 0, { WORKAROUND_STILLCALL, 0 } }, // 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
+ 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
+ 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
+ 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
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, room,script,lvl, object-name, method-name, call,index, workaround
+const SciWorkaroundEntry kStrAt_workarounds[] = {
+ { 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..8a3edb6246
--- /dev/null
+++ b/engines/sci/engine/workarounds.h
@@ -0,0 +1,106 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $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 opcodeMulWorkarounds[];
+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 c3be22b143..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,22 +343,30 @@ sciEvent SciEvent::getFromScummVM() {
return input;
}
-sciEvent SciEvent::get(unsigned int mask) {
+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();
+ }
+}
+
+SciEvent EventManager::getSciEvent(unsigned int mask) {
//sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 };
- sciEvent event = { 0, 0, 0, 0 };
+ SciEvent event = { 0, 0, 0, 0 };
- // 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;
@@ -380,13 +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);
+ _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 c201b2cfb7..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,10 +84,8 @@ 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;
}
}
@@ -95,9 +93,18 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) {
signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal));
if (!(signal & kSignalFrozen)) {
// Call .doit method of that object
- invokeSelector(_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,150 +115,163 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) {
return true;
}
-bool sortHelper(const AnimateEntry* entry1, const AnimateEntry* entry2) {
- if (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;
+ if (entry1.z == entry2.z)
+ return entry1.givenOrderNo < entry2.givenOrderNo;
else
- return entry1->z < entry2->z;
+ return entry1.z < entry2.z;
}
- return entry1->y < entry2->y;
+ 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->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));
+ 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 = 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));
+ 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;
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(loop), listEntry->loopNo);
+ if (it->loopNo >= view->getLoopCount()) {
+ it->loopNo = 0;
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(loop), it->loopNo);
}
- if (listEntry->celNo >= view->getCelCount(listEntry->loopNo)) {
- listEntry->celNo = 0;
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(cel), listEntry->celNo);
+ 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 (!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);
}
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft), listEntry->celRect.left);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop), listEntry->celRect.top);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsRight), listEntry->celRect.right);
- writeSelectorValue(_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);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(priority), listEntry->priority);
+ it->priority = _ports->kernelCoordinateToPriority(it->y);
+ writeSelectorValue(_s->_segMan, curObject, SELECTOR(priority), it->priority);
}
if (signal & kSignalNoUpdate) {
@@ -260,177 +280,154 @@ 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 = readSelector(_s->_segMan, curObject, SELECTOR(underBits));
if (_screen->_picNotValid != 1) {
_paint16->bitsRestore(bitsHandle);
- listEntry->showBitsFlag = true;
+ it->showBitsFlag = true;
} else {
_paint16->bitsFree(bitsHandle);
}
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);
+ 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);
+ 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 = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft));
lsRect.top = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop));
@@ -438,27 +435,27 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) {
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;
}
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft), workerRect.left);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop), workerRect.top);
- writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight), workerRect.right);
- writeSelectorValue(_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();
@@ -466,30 +463,26 @@ 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
writeSelectorValue(_s->_segMan, curObject, SELECTOR(signal), signal);
- listIterator++;
}
- 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
+ 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) {
@@ -499,31 +492,24 @@ void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) {
if (signal & kSignalDisposeMe) {
// Call .delete_ method of that object
- invokeSelector(_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);
@@ -532,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);
+ }
}
@@ -584,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)
@@ -606,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);
@@ -615,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();
@@ -633,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() {
@@ -661,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 706b7182cf..7e82187eed 100644
--- a/engines/sci/graphics/animate.h
+++ b/engines/sci/graphics/animate.h
@@ -51,9 +51,9 @@ 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 {
@@ -73,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;
@@ -90,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);
@@ -105,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);
@@ -126,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 3102edc2fa..0a186115d0 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;
@@ -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) {
@@ -126,14 +127,46 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
int16 x = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(x));
int16 y = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(y));
int16 z = 0;
- if (_kernel->_selectorCache.z > -1)
+ 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 (lookupSelector(_segMan, objectReference, _kernel->_selectorCache.nsTop, NULL, NULL) == kSelectorVariable) {
+#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);
@@ -141,11 +174,11 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) {
}
}
-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 = readSelectorValue(_segMan, curObject, SELECTOR(brLeft));
checkRect.top = readSelectorValue(_segMan, curObject, SELECTOR(brTop));
@@ -154,39 +187,39 @@ bool GfxCompare::kernelCanBeHere(reg_t curObject, reg_t listReference) {
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 = readSelectorValue(_segMan, curObject, SELECTOR(signal));
controlMask = readSelectorValue(_segMan, curObject, SELECTOR(illegalBits));
- result = (isOnControl(GFX_SCREEN_MASK_CONTROL, adjustedRect) & controlMask) ? false : true;
- if ((result) && (signal & (kSignalIgnoreActor | kSignalRemoveView)) == 0) {
+ 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 (lookupSelector(_segMan, object, _kernel->_selectorCache.brLeft, NULL, NULL) == kSelectorVariable) {
+ 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 = (_kernel->_selectorCache.z > -1) ? readSelectorValue(_segMan, object, SELECTOR(z)) : 0;
+ 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));
@@ -196,12 +229,39 @@ void GfxCompare::kernelBaseSetter(reg_t object) {
if (viewId == 0xFFFF) // invalid view
return;
- GfxView *tmpView = _cache->getView(viewId);
+ // must be something wrong with this TODO check - currently it breaks qfg3 right after the intro
+ //uint16 scaleSignal = 0;
+ //if (getSciVersion() >= SCI_VERSION_1_1) {
+ // scaleSignal = readSelectorValue(_segMan, object, SELECTOR(scaleSignal)) & kScaleSignalDoScaling;
+ // if (scaleSignal) {
+ // int16 scaleY = readSelectorValue(_segMan, object, SELECTOR(scaleY));
+ // if (scaleY < 64)
+ // scaleSignal = 0;
+ // }
+ //}
+
Common::Rect celRect;
- tmpView->getCelRect(loopNo, celNo, x, y, z, &celRect);
- celRect.bottom = y + 1;
- celRect.top = celRect.bottom - yStep;
+ //if (!scaleSignal) {
+ GfxView *tmpView = _cache->getView(viewId);
+ if (tmpView->isSci2Hires())
+ _screen->adjustToUpscaledCoordinates(y, x);
+
+ tmpView->getCelRect(loopNo, celNo, x, y, z, celRect);
+
+ if (tmpView->isSci2Hires()) {
+ _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
+ _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
+ }
+
+ celRect.bottom = y + 1;
+ celRect.top = celRect.bottom - yStep;
+ //} else {
+ // celRect.left = readSelectorValue(_segMan, object, SELECTOR(nsLeft));
+ // celRect.right = readSelectorValue(_segMan, object, SELECTOR(nsRight));
+ // celRect.top = readSelectorValue(_segMan, object, SELECTOR(nsTop));
+ // celRect.bottom = readSelectorValue(_segMan, object, SELECTOR(nsBottom));
+ //}
writeSelectorValue(_segMan, object, SELECTOR(brLeft), celRect.left);
writeSelectorValue(_segMan, object, SELECTOR(brRight), celRect.right);
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 26af9741c2..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
diff --git a/engines/sci/graphics/coordadjuster.cpp b/engines/sci/graphics/coordadjuster.cpp
index 422df52f27..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 = readSelectorValue(_s->_segMan, planeObj, SELECTOR(resY));
- //int16 resX = readSelectorValue(_s->_segMan, planeObj, SELECTOR(resX));
- //*x = ( *x * _screen->getWidth()) / resX;
- //*y = ( *y * _screen->getHeight()) / resY;
- x -= readSelectorValue(_segMan, planeObject, SELECTOR(left));
- y -= readSelectorValue(_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 = readSelectorValue(_s->_segMan, planeObj, SELECTOR(resY));
- //int16 resX = readSelectorValue(_s->_segMan, planeObj, SELECTOR(resX));
- x += readSelectorValue(_segMan, planeObject, SELECTOR(left));
- y += readSelectorValue(_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 3cc5ca5447..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 = readSelectorValue(_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 = readSelectorValue(_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,73 +157,140 @@ 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 = readSelectorValue(_segMan, planeObject, SELECTOR(priority));
-
- if (planePriority == -1) // Plane currently not meant to be shown
- continue;
+ for (PlaneList::iterator it = _planes.begin(); it != _planes.end(); it++) {
+ reg_t planeObject = it->object;
+ uint16 planeLastPriority = it->lastPriority;
+ Common::Rect planeRect;
planeRect.top = readSelectorValue(_segMan, planeObject, SELECTOR(top));
planeRect.left = readSelectorValue(_segMan, planeObject, SELECTOR(left));
- planeRect.bottom = readSelectorValue(_segMan, planeObject, SELECTOR(bottom));
- planeRect.right = readSelectorValue(_segMan, planeObject, SELECTOR(right));
- planeResY = readSelectorValue(_segMan, planeObject, SELECTOR(resY));
- planeResX = readSelectorValue(_segMan, planeObject, SELECTOR(resX));
-
- 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;
-
- planeBack = readSelectorValue(_segMan, planeObject, SELECTOR(back));
- if (planeBack) {
- _paint32->fillRect(planeRect, planeBack);
+ planeRect.bottom = readSelectorValue(_segMan, planeObject, SELECTOR(bottom)) + 1;
+ planeRect.right = readSelectorValue(_segMan, planeObject, SELECTOR(right)) + 1;
+
+ // Update priority here, sq6 sets it w/o UpdatePlane
+ uint16 planePriority = it->priority = readSelectorValue(_segMan, planeObject, SELECTOR(priority));
+
+ 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;
+
+ 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 = readSelectorValue(_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 = readSelector(_segMan, itemObject, SELECTOR(plane));
+ reg_t itemObject = _screenItems[itemNr];
+
+ // Remove any invalid items
+ if (!_segMan->isObject(itemObject)) {
+ _screenItems.remove_at(itemNr);
+ itemNr--;
+ continue;
+ }
+
+ reg_t itemPlane = readSelector(_segMan, itemObject, SELECTOR(plane));
if (planeObject == itemPlane) {
// Found an item on current plane
itemEntry->viewId = readSelectorValue(_segMan, itemObject, SELECTOR(view));
@@ -171,18 +300,14 @@ void GfxFrameout::kernelFrameout() {
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->y = ((itemEntry->y * _screen->getHeight()) / planeResY);
- itemEntry->x = ((itemEntry->x * _screen->getWidth()) / planeResX);
- itemEntry->y += planeRect.top;
- itemEntry->x += planeRect.left;
-
- if (itemEntry->priority == 0)
- itemEntry->priority = itemEntry->y;
+ itemEntry->givenOrderNr = itemNr;
itemList.push_back(itemEntry);
itemEntry++;
@@ -190,91 +315,220 @@ void GfxFrameout::kernelFrameout() {
}
}
+ 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 (lookupSelector(_segMan, itemEntry->object, kernel->_selectorCache.text, NULL, NULL) == kSelectorVariable) {
- Common::String text = _segMan->getString(readSelector(_segMan, itemEntry->object, SELECTOR(text)));
- int16 fontRes = readSelectorValue(_segMan, itemEntry->object, SELECTOR(font));
- GfxFont *font = new GfxFontFromResource(_resMan, _screen, fontRes);
- bool dimmed = readSelectorValue(_segMan, itemEntry->object, SELECTOR(dimmed));
- uint16 foreColor = readSelectorValue(_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 e427edd732..0000000000
--- a/engines/sci/graphics/gui.cpp
+++ /dev/null
@@ -1,139 +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);
- _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) {
-}
-
-} // End of namespace Sci
diff --git a/engines/sci/graphics/gui.h b/engines/sci/graphics/gui.h
deleted file mode 100644
index 7663036117..0000000000
--- a/engines/sci/graphics/gui.h
+++ /dev/null
@@ -1,91 +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);
-
- // 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..8f26ca296b 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 {
diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp
index a06e98ccbf..6f2c9596db 100644
--- a/engines/sci/graphics/maciconbar.cpp
+++ b/engines/sci/graphics/maciconbar.cpp
@@ -24,6 +24,7 @@
*/
#include "sci/sci.h"
+#include "sci/engine/kernel.h"
#include "sci/engine/selector.h"
#include "sci/engine/state.h"
#include "sci/graphics/maciconbar.h"
diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp
index 880e1aba12..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,7 +389,7 @@ void GfxMenu::calculateMenuAndItemWidth() {
}
}
-reg_t GfxMenu::kernelSelect(reg_t eventObject) {
+reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) {
int16 eventType = readSelectorValue(_segMan, eventObject, SELECTOR(type));
int16 keyPress, keyModifier;
Common::Point mousePosition;
@@ -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 = 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 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,8 +478,10 @@ 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))
writeSelector(_segMan, eventObject, SELECTOR(claimed), make_reg(0, 1));
@@ -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 ff4f3bec52..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() {
@@ -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;
}
@@ -373,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);
@@ -406,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);
}
@@ -418,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
@@ -447,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
@@ -466,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;
@@ -512,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;
}
}
@@ -540,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;
@@ -555,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 65f9dd0d9c..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,7 +44,7 @@ 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);
@@ -54,8 +53,8 @@ public:
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 3c4cf7e964..5c17f76558 100644
--- a/engines/sci/graphics/palette.cpp
+++ b/engines/sci/graphics/palette.cpp
@@ -30,13 +30,15 @@
#include "sci/sci.h"
#include "sci/engine/state.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;
@@ -57,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;
@@ -81,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;
@@ -99,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++];
@@ -107,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++];
@@ -180,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)
@@ -306,8 +375,6 @@ 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;
@@ -319,11 +386,11 @@ void GfxPalette::setOnScreen() {
}
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;
}
@@ -346,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
@@ -378,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) {
@@ -413,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
@@ -443,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++;
+}
+
+// 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);
+ }
}
-void GfxPalette::doPalVary() {
- // TODO: do palette transition here...
+// 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 a59153f116..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;
@@ -70,14 +73,12 @@ void GfxPicture::draw(int16 animationNr, bool mirroredFlag, bool addToFlag, int1
switch (headerSize) {
case 0x26: // SCI 1.1 VGA picture
_resourceType = SCI_PICTURE_TYPE_SCI11;
- if (_addToFlag)
- _priority = 15;
drawSci11Vga();
break;
#ifdef ENABLE_SCI32
case 0x0e: // SCI32 VGA picture
_resourceType = SCI_PICTURE_TYPE_SCI32;
- drawSci32Vga();
+ //drawSci32Vga();
break;
#endif
default:
@@ -99,28 +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);
+ // 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);
+ 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
@@ -129,45 +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);
- 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) {
+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;
@@ -295,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--;
+ }
}
}
@@ -437,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.
@@ -532,11 +605,12 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) {
// inside picture data for such games
case PIC_OP_SET_PATTERN:
if (_resourceType >= SCI_PICTURE_TYPE_SCI11) {
- if (strcmp(g_sci->getGameID(), "sq4") == 0) {
+ 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;
@@ -618,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);
+ drawCelData(data, _resource->size, curPos, curPos + 8, 0, x, y, 0);
curPos += size;
break;
case PIC_OPX_EGA_SET_PRIORITY_TABLE:
@@ -658,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);
+ 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 5a86539b37..7cd0d71b67 100644
--- a/engines/sci/graphics/picture.h
+++ b/engines/sci/graphics/picture.h
@@ -56,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);
+ 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);
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 cdb6fe4ae1..2e9128cda6 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,15 +52,17 @@ 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) {
+void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *text16) {
int16 offTop = 10;
_usesOldGfxFunctions = usesOldGfxFunctions;
- _gui = gui;
_paint16 = paint16;
_text16 = text16;
@@ -85,37 +89,90 @@ 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
- Common::String gameId = g_sci->getGameID();
- 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() {
+ PortList::iterator it = _windowList.begin();
+ const PortList::iterator end = _windowList.end();
+
+ setPort(_picWind);
+
+ while (it != end) {
+ Port *pPort = *it;
+ if (pPort->id > 2) {
+ // found a window beyond _picWind
+ freeWindow((Window *)pPort);
+ }
+ it++;
+ }
+ _windowList.clear();
+ _windowList.push_front(_wmgrPort);
+ _windowList.push_back(_picWind);
+}
+
void GfxPorts::kernelSetActive(uint16 portId) {
switch (portId) {
case 0:
@@ -124,8 +181,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);
+ }
};
}
@@ -150,10 +212,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);
@@ -163,7 +225,36 @@ 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)
+ removeWindow(wnd, reanimate);
+ else
+ error("GfxPorts::kernelDisposeWindow: Request to dispose invalid port id %d", windowId);
+
+ if ((g_sci->getGameId() == GID_HOYLE4) && (!g_sci->isDemo())) {
+ // WORKAROUND: hoyle 4 has a broken User::handleEvent implementation
+ // first of all iconbar is always set and always gets called with
+ // events checking if event got claimed got removed inside that code
+ // and it will call handleEvent on gameObj afterwards. Iconbar windows
+ // are handled inside iconbar as well including disposing
+ // e.g. iconOK::doit, script 14) and claimed isn't even set. gameObj
+ // handleEvent calling will result in coordinate adjust with a now
+ // invalid port.
+ // We fix this by adjusting the port variable to be global
+ // again when hoyle4 is disposing windows.
+ // This worked because sierra sci leaves old port data, so the pointer
+ // was still valid for a short period of time
+ // TODO: maybe this could get implemented as script patch somehow
+ // although this could get quite tricky to implement (script 996)
+ // IconBar::handleEvent (script 937)
+ // maybe inside export 8 of script 0, which is called by iconOK
+ // and iconReplay
+ // or inside GameControls::hide (script 978) which is called to
+ // actually remove the window
+ reg_t eventObject = _segMan->findObjectByName("uEvt");
+ if (!eventObject.isNull()) {
+ writeSelectorValue(_segMan, eventObject, SELECTOR(port), 0);
+ }
+ }
}
int16 GfxPorts::isFrontWindow(Window *pWnd) {
@@ -200,7 +291,7 @@ 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;
while (id < _windowsById.size() && _windowsById[id]) {
@@ -214,7 +305,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;
}
@@ -227,8 +318,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))
@@ -343,12 +436,12 @@ 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);
_paint16->bitsRestore(pWnd->hSaved2);
@@ -358,6 +451,15 @@ void GfxPorts::disposeWindow(Window *pWnd, bool reanimate) {
_paint16->kernelGraphRedrawBox(pWnd->restoreRect);
_windowList.remove(pWnd);
setPort(_windowList.back());
+ _windowsById[pWnd->id] = NULL;
+ delete pWnd;
+}
+
+void GfxPorts::freeWindow(Window *pWnd) {
+ if (!pWnd->hSaved1.isNull())
+ _segMan->freeHunkEntry(pWnd->hSaved1);
+ if (!pWnd->hSaved2.isNull())
+ _segMan->freeHunkEntry(pWnd->hSaved1);
_windowsById[pWnd->id] = 0;
delete pWnd;
}
@@ -378,13 +480,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;
@@ -496,6 +594,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) {
@@ -511,22 +614,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 c8ce6b3470..f7f0721eb7 100644
--- a/engines/sci/graphics/ports.h
+++ b/engines/sci/graphics/ports.h
@@ -45,7 +45,8 @@ public:
GfxPorts(SegManager *segMan, GfxScreen *screen);
~GfxPorts();
- void init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, GfxText16 *text16);
+ void init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *text16);
+ void reset();
void kernelSetActive(uint16 portId);
Common::Rect kernelGetPicWindow(int16 &picTop, int16 &picLeft);
@@ -57,9 +58,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 +83,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 +103,6 @@ private:
typedef Common::List<Port *> PortList;
SegManager *_segMan;
- SciGui *_gui;
GfxPaint16 *_paint16;
GfxScreen *_screen;
GfxText16 *_text16;
@@ -122,9 +122,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 0e054d5a76..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;
@@ -97,9 +125,9 @@ GfxScreen::GfxScreen(ResourceManager *resMan, int16 width, int16 height, int ups
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 (!scumm_stricmp(g_sci->getGameID(), "kq6"))
+ if (g_sci->getGameId() == GID_KQ6)
initGraphics(_displayWidth, _displayHeight + 26, _displayWidth > 320);
- else if (!scumm_stricmp(g_sci->getGameID(), "qfg1"))
+ else if (g_sci->getGameId() == GID_QFG1VGA)
initGraphics(_displayWidth, _displayHeight + 20, _displayWidth > 320);
else
error("Unknown SCI1.1 Mac game");
@@ -141,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");
@@ -192,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;
@@ -263,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
@@ -400,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);
}
}
@@ -435,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
@@ -458,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;
@@ -557,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;
}
}
@@ -578,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 a2cfd38f95..dae2807cc2 100644
--- a/engines/sci/module.mk
+++ b/engines/sci/module.mk
@@ -10,7 +10,6 @@ MODULE_OBJS := \
sci.o \
util.o \
engine/features.o \
- engine/game.o \
engine/gc.o \
engine/kernel.o \
engine/kevent.o \
@@ -26,6 +25,7 @@ MODULE_OBJS := \
engine/kscripts.o \
engine/ksound.o \
engine/kstring.o \
+ engine/kvideo.o \
engine/message.o \
engine/savegame.o \
engine/script.o \
@@ -36,6 +36,7 @@ MODULE_OBJS := \
engine/state.o \
engine/static_selectors.o \
engine/vm.o \
+ engine/workarounds.o \
graphics/animate.o \
graphics/cache.o \
graphics/compare.o \
@@ -44,7 +45,6 @@ MODULE_OBJS := \
graphics/cursor.o \
graphics/font.o \
graphics/fontsjis.o \
- graphics/gui.o \
graphics/maciconbar.o \
graphics/menu.o \
graphics/paint.o \
@@ -65,21 +65,16 @@ 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
diff --git a/engines/sci/parser/grammar.cpp b/engines/sci/parser/grammar.cpp
index 070e6767cf..6f37b49919 100644
--- a/engines/sci/parser/grammar.cpp
+++ b/engines/sci/parser/grammar.cpp
@@ -422,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) {
@@ -565,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 f49704372a..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,1840 +46,622 @@ 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
-
-#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 */
-}
-
-
-
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#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
-
-
-
-/* Copy the second part of user declarations. */
-
-
-/* Line 216 of yacc.c. */
-
-
-#ifdef short
-# undef short
-#endif
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#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
-
-#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
-
-#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
-
-/* Suppress unused-variable warnings by "using" E. */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* 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;
-}
-#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
-};
-
-/* 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 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
};
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const yytype_uint8 yyrline[] =
-{
- 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
+enum SaidWord {
+ WORD_NONE = 0x0ffe,
+ WORD_ANY = 0x0fff
};
-#endif
-#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
-# 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
-/* 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
-};
+// 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)
-/* 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
-};
+static ParseTreeNode said_tree[VOCAB_TREE_NODES];
-/* 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[] =
-{
- 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
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yytype_int8 yydefgoto[] =
-{
- -1, 8, 27, 9, 28, 46, 10, 11, 12, 13,
- 14, 15, 37
-};
-
-/* 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
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int8 yypgoto[] =
-{
- -24, -24, -23, -24, -24, -24, 68, -24, 0, -2,
- 69, -4, 26
-};
-
-/* 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
-};
-
-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
-};
-
-/* 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
-
-
-/* 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. */
-
-#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
+typedef int wgroup_t;
+typedef int said_spec_t;
-/* YYLEX -- calling `yylex' with the right arguments. */
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
+static ParseTreeNode* said_next_node() {
+ assert(said_tree_pos > 0 && said_tree_pos < VOCAB_TREE_NODES);
-/* 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;
- }
+ return &said_tree[said_tree_pos++];
}
+static ParseTreeNode* said_leaf_node(ParseTreeNode* pos, int value) {
+ pos->type = kParseTreeLeafNode;
+ pos->value = value;
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-#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]);
-
- yy_symbol_value_print (yyoutput, yytype, yyvaluep);
- YYFPRINTF (yyoutput, ")");
+ return pos;
}
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included). |
-`------------------------------------------------------------------*/
+static ParseTreeNode* said_word_node(ParseTreeNode* pos, int value) {
+ pos->type = kParseTreeWordNode;
+ pos->value = value;
-#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");
+ return pos;
}
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (YYID (0))
-
+static ParseTreeNode* said_branch_node(ParseTreeNode* pos,
+ ParseTreeNode* left,
+ ParseTreeNode* right) {
+ pos->type = kParseTreeBranchNode;
+ pos->left = left;
+ pos->right = right;
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced. |
-`------------------------------------------------*/
-
-#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");
- }
+ return pos;
}
-# 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
+static ParseTreeNode* said_branch_attach_left(ParseTreeNode* pos,
+ ParseTreeNode* left) {
+ pos->type = kParseTreeBranchNode;
+ pos->left = left;
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
- if the built-in stack extension method is used).
-
- Do not make this value too large; the results are undefined if
- YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
- evaluated with infinite-precision integer arithmetic. */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
+ return pos;
-
+}
-#if YYERROR_VERBOSE
+static ParseTreeNode* said_branch_attach_right(ParseTreeNode* pos,
+ ParseTreeNode* right) {
+ pos->type = kParseTreeBranchNode;
+ pos->right = right;
-# 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;
+ return pos;
}
-# 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;
- while ((*yyd++ = *yys++) != '\0')
- continue;
- 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 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);
+/*
+ pos
+ / \
+ . \
+ *
+ / \
+ / 0
+ *
+ / \
+ / \
+ / subtree
+ major / \
+ / .
+ minor
+
+ . = unchanged child node
+ * = new branch node
+ 0 = NULL child node. (Location for future siblings of the subtree)
- if (!yymsg)
- yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+*/
- switch (yytype)
- {
+static bool said_attach_subtree(ParseTreeNode* pos, int major, int minor,
+ ParseTreeNode* subtree) {
+ bool retval = true;
- default:
- break;
- }
-}
-
+ 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));
-/* Prevent warnings from -Wmissing-prototypes. */
+ return retval;
+}
-#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 */
-/* The look-ahead symbol. */
-int yychar;
+/*****************/
+/**** Parsing ****/
+/*****************/
-/* The semantic value of the look-ahead symbol. */
-YYSTYPE yylval;
+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);
-/* Number of syntax errors so far. */
-int yynerrs;
+static bool parseWord(ParseTreeNode* parentNode)
+{
+ int token = said_tokens[said_token];
+ if (token & 0x8000)
+ return false;
+ said_token++;
+ ParseTreeNode* newNode = said_word_node(said_next_node(), token);
-/*----------.
-| yyparse. |
-`----------*/
+ parentNode->right = newNode;
-#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 ()
+ return true;
+}
-#endif
-#endif
+static bool parsePart2(ParseTreeNode* parentNode, bool& nonempty)
{
-
- 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
+ // Store current state for rolling back if we fail
+ int curToken = said_token;
+ int curTreePos = said_tree_pos;
+ ParseTreeNode* curRightChild = parentNode->right;
- /* 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))
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
- YYSIZE_T yystacksize = YYINITDEPTH;
-
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
+ nonempty = true;
+ bool found;
- /* The number of symbols on the RHS of the reduced rule.
- Keep to zero when no symbol should be popped. */
- int yylen = 0;
+ found = parseSlash(newNode);
- YYDPRINTF ((stderr, "Starting parse\n"));
+ if (found) {
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
+ said_attach_subtree(parentNode, 0x142, 0x14a, 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. */
+ return true;
- yyssp = yyss;
- yyvsp = yyvs;
+ } else if (said_tokens[said_token] == TOKEN_BRACKETO) {
+ said_token++;
+
+ found = parsePart2(newNode, nonempty);
- goto yysetstate;
+ if (found) {
-/*------------------------------------------------------------.
-| 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;
- }
+ if (said_tokens[said_token] == TOKEN_BRACKETC) {
+ said_token++;
- if (yyn == YYFINAL)
- YYACCEPT;
+ said_attach_subtree(parentNode, 0x152, 0x142, newNode);
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
+ return true;
+ }
+ }
- /* 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;
+ // CHECKME: this doesn't look right if the [] section matched partially
+ // Should the below 'if' be an 'else if' ?
- yystate = yyn;
- *++yyvsp = yylval;
+ if (said_tokens[said_token] == TOKEN_SLASH) {
+ said_token++;
- goto yynewstate;
+ nonempty = false;
+ return true;
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state. |
-`-----------------------------------------------------------*/
-yydefault:
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
- goto yyreduce;
+ }
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
-/*-----------------------------.
-| yyreduce -- Do a reduction. |
-`-----------------------------*/
-yyreduce:
- /* yyn is the number of a rule to reduce with. */
- yylen = yyr2[yyn];
+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;
- /* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
- 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];
+ bool found;
+ nonempty = true;
- YY_REDUCE_PRINT (yyn);
- switch (yyn)
- {
- case 2:
+ found = parseSlash(newNode);
- { (yyval) = said_top_branch(said_attach_branch((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)]))); ;}
- break;
+ if (found) {
- case 3:
+ said_attach_subtree(parentNode, 0x143, 0x14a, newNode);
- { (yyval) = said_top_branch(said_attach_branch((yyvsp[(1) - (3)]), said_attach_branch((yyvsp[(2) - (3)]), (yyvsp[(3) - (3)])))); ;}
- break;
+ return true;
- case 4:
+ } else if (said_tokens[said_token] == TOKEN_BRACKETO) {
+ said_token++;
+
+ found = parsePart3(newNode, nonempty);
- { (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;
+ if (found) {
- case 5:
+ if (said_tokens[said_token] == TOKEN_BRACKETC) {
+ said_token++;
- { (yyval) = SAID_BRANCH_NULL; ;}
- break;
+ said_attach_subtree(parentNode, 0x152, 0x143, newNode);
- case 6:
+ return true;
+ }
+ }
- { (yyval) = said_paren(said_value(0x14b, said_value(0xf900, said_terminal(0xf900))), SAID_BRANCH_NULL); ;}
- break;
+ }
- case 7:
+ // CHECKME: this doesn't look right if the [] section matched partially
+ // Should the below 'if' be an 'else if' ?
- { (yyval) = SAID_BRANCH_NULL; ;}
- break;
+ if (said_tokens[said_token] == TOKEN_SLASH) {
+ said_token++;
- case 8:
+ nonempty = false;
- { (yyval) = said_paren(said_value(0x141, said_value(0x149, (yyvsp[(1) - (1)]))), SAID_BRANCH_NULL); ;}
- break;
+ return true;
- case 9:
+ }
- { (yyval) = said_aug_branch(0x142, 0x14a, (yyvsp[(2) - (2)]), SAID_BRANCH_NULL); ;}
- break;
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
- case 10:
- { (yyval) = said_aug_branch(0x152, 0x142, said_aug_branch(0x142, 0x14a, (yyvsp[(3) - (4)]), SAID_BRANCH_NULL), SAID_BRANCH_NULL); ;}
- break;
+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;
- case 11:
+ if (said_tokens[said_token] == TOKEN_SLASH) {
+ said_token++;
- { (yyval) = SAID_BRANCH_NULL; ;}
- break;
+ bool found = parseExpr(parentNode);
- case 12:
+ if (found)
+ return true;
- { (yyval) = said_aug_branch(0x143, 0x14a, (yyvsp[(2) - (2)]), SAID_BRANCH_NULL); ;}
- break;
+ }
- case 13:
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
- { (yyval) = said_aug_branch(0x152, 0x143, said_aug_branch(0x143, 0x14a, (yyvsp[(3) - (4)]), SAID_BRANCH_NULL), SAID_BRANCH_NULL); ;}
- break;
- case 14:
+static bool parseRef(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_BRANCH_NULL; ;}
- break;
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
- case 15:
+ ParseTreeNode* newParent = parentNode;
- { (yyval) = said_paren(said_value(0x141, said_value(0x153, said_terminal((yyvsp[(1) - (1)])))), SAID_BRANCH_NULL); ;}
- break;
+ bool found;
- case 16:
+ if (said_tokens[said_token] == TOKEN_LT) {
+ said_token++;
- { (yyval) = said_aug_branch(0x141, 0x14f, (yyvsp[(1) - (1)]), SAID_BRANCH_NULL); ;}
- break;
+ found = parseList(newNode);
- case 17:
+ if (found) {
- { (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;
+ said_attach_subtree(newParent, 0x144, 0x14f, newNode);
- case 18:
+ newParent = newParent->right;
+
+ newNode = said_branch_node(said_next_node(), 0, 0);
- { (yyval) = (yyvsp[(1) - (1)]); ;}
- break;
+ found = parseRef(newNode);
- case 19:
+ if (found) {
- { (yyval) = said_aug_branch(0x141, 0x14c, (yyvsp[(2) - (3)]), SAID_BRANCH_NULL); ;}
- break;
+ said_attach_subtree(newParent, 0x141, 0x144, newNode);
- case 20:
+ }
- { (yyval) = said_attach_branch((yyvsp[(1) - (3)]), (yyvsp[(3) - (3)])); ;}
- break;
+ return true;
- case 21:
+ }
- { (yyval) = said_attach_branch((yyvsp[(1) - (4)]), (yyvsp[(3) - (4)])); ;}
- break;
+ }
- case 22:
+ // NB: This is not an "else if'.
+ // If there is a "< [ ... ]", that is parsed as "< ..."
- { (yyval) = said_attach_branch((yyvsp[(1) - (5)]), (yyvsp[(3) - (5)])); ;}
- break;
+ if (said_tokens[said_token] == TOKEN_BRACKETO) {
+ said_token++;
+
+ found = parseRef(newNode);
- case 23:
+ if (found) {
- { (yyval) = said_attach_branch((yyvsp[(1) - (2)]), (yyvsp[(2) - (2)])); ;}
- break;
+ if (said_tokens[said_token] == TOKEN_BRACKETC) {
+ said_token++;
- case 24:
+ said_attach_subtree(parentNode, 0x152, 0x144, newNode);
- { (yyval) = (yyvsp[(1) - (1)]); ;}
- break;
+ return true;
+ }
+ }
- case 25:
+ }
- { (yyval) = (yyvsp[(1) - (1)]); ;}
- break;
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
- case 26:
+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;
- { (yyval) = (yyvsp[(1) - (1)]); ;}
- break;
+ if (said_tokens[said_token] == TOKEN_COMMA) {
+ said_token++;
- case 27:
+ bool found = parseList(parentNode);
- { (yyval) = said_aug_branch(0x152, 0x144, (yyvsp[(2) - (3)]), SAID_BRANCH_NULL); ;}
- break;
+ if (found)
+ return true;
- case 28:
+ }
- { (yyval) = said_attach_branch((yyvsp[(1) - (4)]), said_aug_branch(0x152, 0x144, (yyvsp[(3) - (4)]), SAID_BRANCH_NULL)); ;}
- break;
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
- case 29:
+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;
- { (yyval) = said_aug_branch(0x144, 0x14f, (yyvsp[(2) - (3)]), (yyvsp[(3) - (3)])); ;}
- break;
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
- case 30:
+ bool found;
- { (yyval) = said_aug_branch(0x144, 0x14f, said_aug_branch(0x141, 0x144, (yyvsp[(2) - (4)]), SAID_BRANCH_NULL), SAID_BRANCH_NULL); ;}
- break;
+ if (said_tokens[said_token] == TOKEN_BRACKETO) {
+ said_token++;
- case 31:
+ found = parseExpr(newNode);
- { (yyval) = said_aug_branch(0x144, 0x14f, (yyvsp[(2) - (2)]), SAID_BRANCH_NULL); ;}
- break;
+ if (found) {
- case 32:
+ if (said_tokens[said_token] == TOKEN_BRACKETC) {
+ said_token++;
- { (yyval) = said_aug_branch(0x152, 0x144, said_aug_branch(0x144, 0x14f, (yyvsp[(3) - (4)]), SAID_BRANCH_NULL), SAID_BRANCH_NULL); ;}
- break;
+ said_attach_subtree(parentNode, 0x152, 0x14c, newNode);
- case 33:
+ return true;
+ }
+ }
- { (yyval) = said_aug_branch(0x141, 0x144, said_aug_branch(0x144, 0x14f, (yyvsp[(2) - (3)]), SAID_BRANCH_NULL), (yyvsp[(3) - (3)])); ;}
- break;
+ } else if (said_tokens[said_token] == TOKEN_PARENO) {
+ said_token++;
- case 34:
+ found = parseExpr(newNode);
- { (yyval) = said_aug_branch(0x141, 0x144, said_aug_branch(0x144, 0x14f, (yyvsp[(2) - (2)]), SAID_BRANCH_NULL), SAID_BRANCH_NULL); ;}
- break;
+ if (found) {
- case 35:
+ if (said_tokens[said_token] == TOKEN_PARENC) {
+ said_token++;
- { (yyval) = said_aug_branch(0x141, 0x14c, (yyvsp[(2) - (4)]), SAID_BRANCH_NULL); ;}
- break;
+ said_attach_subtree(parentNode, 0x141, 0x14c, newNode);
+ return true;
+ }
+ }
-/* Line 1267 of yacc.c. */
+ } else if (parseWord(newNode)) {
- default: break;
- }
- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+ said_attach_subtree(parentNode, 0x141, 0x153, newNode);
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
+ return true;
- *++yyvsp = yyval;
+ }
- /* 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];
+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;
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
+ bool found;
- goto yynewstate;
+ ParseTreeNode* newParent = parentNode;
+ found = parseListEntry(newParent);
-/*------------------------------------.
-| 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 (found) {
+ newParent = newParent->right;
+ found = parseComma(newParent);
- 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;
- }
}
- /* Pop the current state because it cannot handle the error token. */
- if (yyssp == yyss)
- YYABORT;
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
+}
+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;
- yydestruct ("Error: popping",
- yystos[yystate], yyvsp);
- YYPOPSTACK (1);
- yystate = *yyssp;
- YY_STACK_PRINT (yyss, yyssp);
- }
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
- if (yyn == YYFINAL)
- YYACCEPT;
+ bool ret = false;
+ bool found;
- *++yyvsp = yylval;
+ ParseTreeNode* newParent = parentNode;
+ found = parseList(newNode);
- /* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+ if (found) {
+ ret = true;
- yystate = yyn;
- goto yynewstate;
+ said_attach_subtree(newParent, 0x141, 0x14F, newNode);
+ newParent = newParent->right;
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here. |
-`-------------------------------------*/
-yyacceptlab:
- yyresult = 0;
- goto yyreturn;
+ }
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here. |
-`-----------------------------------*/
-yyabortlab:
- yyresult = 1;
- goto yyreturn;
+ found = parseRef(newParent);
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here. |
-`-------------------------------------------------*/
-yyexhaustedlab:
- yyerror (YY_("memory exhausted"));
- yyresult = 2;
- /* Fall through. */
-#endif
+ if (found || ret)
+ return true;
-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);
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
}
+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;
+ ParseTreeNode* newNode = said_branch_node(said_next_node(), 0, 0);
+ bool ret = false;
+ bool found;
-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};
+ ParseTreeNode* newParent = parentNode;
-static int yylex() {
- int retval = said_tokens[said_token++];
+ found = parseExpr(newNode);
- 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 (found) {
+ // Sentence part 1 found
+ said_attach_subtree(newParent, 0x141, 0x149, newNode);
- return retval;
-}
+ newParent = newParent->right;
-static int said_next_node() {
- return ((said_tree_pos == 0) || (said_tree_pos >= VOCAB_TREE_NODES)) ? said_tree_pos = 0 : said_tree_pos++;
-}
+ ret = true;
+ }
-#define SAID_NEXT_NODE said_next_node()
+ bool nonempty;
-static int said_leaf_node(tree_t pos, int value) {
- said_tree[pos].type = kParseTreeLeafNode;
+ found = parsePart2(newParent, nonempty);
- if (value != VALUE_IGNORE)
- said_tree[pos].content.value = value;
+ if (found) {
- return pos;
-}
+ ret = true;
-static int said_branch_node(tree_t pos, int left, int right) {
- said_tree[pos].type = kParseTreeBranchNode;
+ if (nonempty) // non-empty part found
+ newParent = newParent->right;
- if (left != VALUE_IGNORE)
- said_tree[pos].content.branches[0] = left;
- if (right != VALUE_IGNORE)
- said_tree[pos].content.branches[1] = right;
+ found = parsePart3(newParent, nonempty);
- return pos;
-}
+ if (found) {
-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;
-}
+ if (nonempty)
+ newParent = newParent->right;
+ }
+ }
-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 (said_tokens[said_token] == TOKEN_GT) {
+ said_token++;
-}
+ newNode = said_branch_node(said_next_node(), 0,
+ said_leaf_node(said_next_node(), TOKEN_GT));
-static tree_t said_terminal(int val) {
- return said_leaf_node(SAID_NEXT_NODE, val);
-}
+ said_attach_subtree(newParent, 0x14B, TOKEN_GT, newNode);
-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;
+ if (ret)
+ return true;
+
+ // Rollback
+ said_token = curToken;
+ said_tree_pos = curTreePos;
+ parentNode->right = curRightChild;
+ return false;
}
-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;
+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
- if (!base)
- return 0; // Happens if we're out of space
+ said_tree_pos = SAID_TREE_START;
- said_branch_node(base, VALUE_IGNORE, attacheant);
+ bool ret = parseSpec(&said_tree[2]);
- return base;
-}
+ if (!ret)
+ return false;
-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
+ if (said_tokens[said_token] != TOKEN_TERM) {
+ // No terminator, so parse error.
- ++said_blessed;
+ // Rollback
+ said_tree[2].right = 0;
+ said_token = 0;
+ said_tree_pos = SAID_TREE_START;
+ return false;
+ }
- return 0;
+ return true;
}
-static int said_parse_spec(byte *spec) {
+static int said_parse_spec(const byte *spec) {
int nextitem;
- said_parse_error = NULL;
said_token = 0;
said_tokens_nr = 0;
- said_blessed = 0;
said_tree_pos = SAID_TREE_START;
@@ -2025,26 +674,13 @@ static int said_parse_spec(byte *spec) {
} while ((nextitem != SAID_TERM) && (said_tokens_nr < MAX_SAID_TOKENS));
- if (nextitem == SAID_TERM)
- yyparse();
- else {
+ if (nextitem != SAID_TERM) {
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");
+ if (!buildSaidTree()) {
+ warning("Error while parsing SAID spec");
return 1;
}
@@ -2055,385 +691,304 @@ static int said_parse_spec(byte *spec) {
/**** Augmentation ****/
/**********************/
-// primitive functions
+static bool dontclaim;
+static int outputDepth;
-#define AUG_READ_BRANCH(a, br, p) \
- if (tree[p].type != kParseTreeBranchNode) \
- return 0; \
- a = tree[p].content.branches[br];
+enum ScanSaidType {
+ SCAN_SAID_AND = 0,
+ SCAN_SAID_OR = 1
+};
-#define AUG_READ_VALUE(a, p) \
- if (tree[p].type != kParseTreeLeafNode) \
- return 0; \
- a = tree[p].content.value;
+static int matchTrees(ParseTreeNode* parseT, ParseTreeNode* saidT);
+static int scanSaidChildren(ParseTreeNode* parseT, ParseTreeNode* saidT,
+ ScanSaidType type);
+static int scanParseChildren(ParseTreeNode* parseT, ParseTreeNode* saidT);
-#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;
+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
- 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 matchTrees(ParseTreeNode* parseT, ParseTreeNode* saidT)
+{
+ outputDepth++;
+ scidprintf("%*smatchTrees on ", outputDepth, "");
+ node_print_desc(parseT);
+ scidprintf(" and ");
+ node_print_desc(saidT);
+ scidprintf("\n");
-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;
+ bool inParen = node_minor(saidT) == 0x14F || node_minor(saidT) == 0x150;
+ bool inBracket = node_major(saidT) == 0x152;
- 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);
+ int ret;
- return val;
-}
+ if (node_major(parseT) != 0x141 &&
+ node_major(saidT) != 0x141 && node_major(saidT) != 0x152 &&
+ node_major(saidT) != node_major(parseT))
+ {
+ ret = -1;
+ }
-static int aug_get_base_node(parse_tree_node_t *tree) {
- int startpos = 0;
- AUG_READ_BRANCH(startpos, 1, startpos);
+ // parse major is 0x141 and/or
+ // said major is 0x141/0x152 and/or
+ // said major is parse major
- return startpos;
-}
+ else if (node_is_terminal(saidT) && node_is_terminal(parseT) ) {
-// semi-primitive functions
+ // both saidT and parseT are terminals
-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);
+ int said_val = node_terminal_value(saidT);
+ int parse_val = node_terminal_value(parseT);
- return aug_get_next_sibling(tree, pos, first, second);
-}
+ if (said_val != WORD_NONE &&
+ (said_val == parse_val || said_val == WORD_ANY ||
+ parse_val == WORD_ANY))
+ ret = 1;
+ else
+ ret = -1;
-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);
+ scidprintf("%*smatchTrees matching terminals: %03x vs %03x (%d)\n",
+ outputDepth, "", parse_val, said_val, ret);
- //if (major == WORD_TYPE_REF)
- // refbranch = 1;
+ } else if (node_is_terminal(saidT) && !node_is_terminal(parseT)) {
- 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
- }
+ // saidT is a terminal, but parseT isn't
- base_words[*base_words_nr] = word; // register word
- ++(*base_words_nr);
+ if (node_major(parseT) == 0x141 ||
+ node_major(parseT) == node_major(saidT))
+ ret = scanParseChildren(parseT->right->right, saidT);
+ else
+ ret = 0;
- }
- if (major == WORD_TYPE_REF || refbranch) {
- if ((*ref_words_nr) == maxwords) {
- warning("Out of reference words");
- return; // return gracefully
- }
+ } else if (node_is_terminal(parseT)) {
- ref_words[*ref_words_nr] = word; // register word
- ++(*ref_words_nr);
+ // parseT is a terminal, but saidT isn't
- }
- 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 (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 // 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);
+ } else if (node_major(saidT) != 0x141 && node_major(saidT) != 0x152 &&
+ node_major(saidT) != node_major(parseT)) {
- pos = aug_get_next_sibling(tree, pos, &major, &minor);
- }
-}
+ // parseT and saidT both aren't terminals
+ // said major is not 0x141 or 0x152 or parse major
+ ret = scanParseChildren(parseT->right->right, saidT);
-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;
+ } else {
- aug_find_words_recursively(tree, startpos, base_words, base_words_nr, ref_words, ref_words_nr, maxwords, 0);
-}
+ // parseT and saidT are both not terminals,
+ // said major 0x141 or 0x152 or equal to parse major
+ ret = scanSaidChildren(parseT->right->right, saidT->right->right,
+ inParen ? SCAN_SAID_OR : SCAN_SAID_AND);
-static int aug_contains_word(int *list, int length, int word) {
- int i;
+ }
- if (word == ANYWORD)
- return (length);
+ if (inBracket && ret == 0) {
+ scidprintf("%*smatchTrees changing ret to 1 due to brackets\n",
+ outputDepth, "");
+ ret = 1;
+ }
- for (i = 0; i < length; i++)
- if (list[i] == word)
- return 1;
+ scidprintf("%*smatchTrees returning %d\n", outputDepth, "", ret);
+ outputDepth--;
- return 0;
+ return ret;
}
-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 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");
-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 ret = 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);
+ assert(!(type == SCAN_SAID_OR && !saidT));
- }
- 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);
+ while (saidT) {
+ assert(saidT->type == kParseTreeBranchNode);
- }
- break;
+ ParseTreeNode* saidChild = saidT->left;
+ assert(saidChild);
- 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 (node_major(saidChild) != 0x145) {
- scidprintf("Didn't match subexpression; checking sub-bracked predicate %03x\n", cmajor);
+ ret = scanParseChildren(parseT, saidChild);
- switch (cmajor) {
- case WORD_TYPE_BASE:
- if (!base_words_nr)
- return 1;
- break;
+ if (type == SCAN_SAID_AND && ret != 1)
+ break;
- case WORD_TYPE_REF:
- if (!ref_words_nr)
- return 1;
- break;
+ if (type == SCAN_SAID_OR && ret == 1)
+ break;
- default:
- warning("augment_match_expression_p(): (subp1) Unkonwn sub-bracket predicate %03x", cmajor);
}
- break;
+ saidT = saidT->right;
- default:
- warning("augment_match_expression_p(): Unknown predicate %03x", major);
+ }
+ scidprintf("%*sscanSaid returning %d\n", outputDepth, "", ret);
+ outputDepth--;
+ return ret;
+}
+
+
+static int scanParseChildren(ParseTreeNode* parseT, ParseTreeNode* saidT) {
+
+ outputDepth++;
+ scidprintf("%*sscanParse on ", outputDepth, "");
+ node_print_desc(parseT);
+ scidprintf(" and ");
+ node_print_desc(saidT);
+ scidprintf("\n");
+
+ if (node_major(saidT) == 0x14B) {
+ dontclaim = true;
+ scidprintf("%*sscanParse returning 1 (0x14B)\n", outputDepth, "");
+ outputDepth--;
+ return 1;
}
- scidprintf("augment_match_expression_p(): Generic failure\n");
+ bool inParen = node_minor(saidT) == 0x14F || node_minor(saidT) == 0x150;
+ bool inBracket = node_major(saidT) == 0x152;
- return 0;
-}
+ int ret;
-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)));
+ // descend further down saidT before actually scanning parseT
+ if ((node_major(saidT) == 0x141 || node_major(saidT) == 0x152) &&
+ !node_is_terminal(saidT)) {
- return 1;
-}
+ ret = scanSaidChildren(parseT, saidT->right->right,
+ inParen ? SCAN_SAID_OR : SCAN_SAID_AND );
-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;
+ } else if (parseT && parseT->left->type == kParseTreeBranchNode) {
- scidprintf("Augmenting (%03x %03x\n", major, minor);
+ ret = 0;
+ int subresult = 0;
- 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;
- }
- }
+ while (parseT) {
+ assert(parseT->type == kParseTreeBranchNode);
- if ((major < 0x141) || (major > 0x143)) {
- scidprintf("augment_sentence_part(): Unexpected sentence part major number %03x\n", major);
- return 0;
- }
+ ParseTreeNode* parseChild = parseT->left;
+ assert(parseChild);
- 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("%*sscanning next: ", outputDepth, "");
+ node_print_desc(parseChild);
+ scidprintf("\n");
- 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
+ if (node_major(parseChild) == node_major(saidT) ||
+ node_major(parseChild) == 0x141)
+ subresult = matchTrees(parseChild, saidT);
- success = augment_sentence_expression(saidt, augment_pos, parset, parse_basepos, major, minor,
- base_words, base_words_nr, ref_words, ref_words_nr);
+ if (subresult != 0)
+ ret = subresult;
+
+ if (ret == 1)
+ break;
+
+ parseT = parseT->right;
- if (success) {
- scidprintf("SUCCESS on augmenting (%03x %03x\n", major, minor);
- return 1;
- }
}
+
+ // ret is now:
+ // 1 if ANY matchTrees(parseSibling, saidTree) returned 1
+ // ELSE: -1 if ANY returned -1
+ // ELSE: 0
+
+ } else {
+
+ ret = matchTrees(parseT, saidT);
+
}
- if (optional && (foundwords == 0)) {
- scidprintf("Found no words and optional branch => SUCCESS on augmenting (%03x %03x\n", major, minor);
- return 1;
+ if (inBracket && ret == 0) {
+ scidprintf("%*sscanParse changing ret to 1 due to brackets\n",
+ outputDepth, "");
+ ret = 1;
}
- scidprintf("FAILURE on augmenting (%03x %03x\n", major, minor);
- return 0;
+ scidprintf("%*sscanParse returning %d\n", outputDepth, "", ret);
+ outputDepth--;
+
+ return ret;
}
-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;
- }
+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");
- 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
- }
- }
+ dontclaim = false;
+
+ int ret = matchTrees(parseT, saidT);
+
+ scidprintf("matchTrees returned %d\n", ret);
- scidprintf("Returning success with dontclaim=%d\n", dontclaim);
+ if (ret != 1)
+ return 0;
if (dontclaim)
return SAID_PARTIAL_MATCH;
- else
- return 1; // full match
+
+ return 1;
}
@@ -2441,22 +996,19 @@ static int augment_parse_nodes(parse_tree_node_t *parset, parse_tree_node_t *sai
/**** Main code ****/
/*******************/
-int said(EngineState *s, byte *spec, bool verbose) {
+int said(EngineState *s, const byte *spec, bool verbose) {
int retval;
Vocabulary *voc = g_sci->getVocabulary();
- parse_tree_node_t *parse_tree_ptr = voc->_parserNodes;
+ ParseTreeNode *parse_tree_ptr = voc->_parserNodes;
if (voc->parserIsValid) {
- if (said_parse_spec(spec)) {
- printf("Offending spec was: ");
- voc->decipherSaidBlock(spec);
+ if (said_parse_spec(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]));
+ vocab_dump_parse_tree("Said-tree", said_tree);
+ retval = augment_parse_nodes(parse_tree_ptr, said_tree);
if (!retval)
return SAID_NO_MATCH;
@@ -2470,15 +1022,108 @@ int said(EngineState *s, byte *spec, bool verbose) {
}
-#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;
+/*
+
+Some test expressions for in the ScummVM debugging console, using
+Codename: ICEMAN's vocabulary:
+
+
+
+said green board & [!*] / 8af < 1f6
+True
+
+said get green board & [!*] / 8af < 1f6
+False
+
+said green board & [!*] / 8af [< 1f6 ]
+True
+
+said climb up & 19b , 426 [< 142 ] [/ 81e ]
+True
+
+said climb up ladder & 19b , 426 [< 142 ] [/ 81e ]
+True
+
+said climb down & 19b , 426 [< 142 ] [/ 81e ]
+False
+
+said climb up tree & 19b , 426 [< 142 ] [/ 81e ]
+False
+
+said climb up & 19b , 446 , 426 [< 143 ] [/ 81e ]
+False
+
+said climb down & 19b , 446 , 426 [< 143 ] [/ 81e ]
+True
+
+said use green device & 1a5 / 8c1 [< 21d ]
+False
+
+said use electronic device & 1a5 / 8c1 [< 21d ]
+True
+
+said use device & 1a5 / 8c1 [< 21d ]
+True
+
+said eat & 429 [/ !* ]
+True
+
+said eat ladder & 429 [/ !* ]
+False
+
+said look at the ladder & 3f8 / 81e [< !* ]
+True
+
+said look at the green ladder & 3f8 / 81e [< !* ]
+False
+
+said look green book & / 7f6 [< 8d2 ]
+False
+
+said look green book & 3f8 [< ca ]
+True
+
+said get a blue board for the green ladder & 3f9 / 8af [ < 1f6 ] / 81e < 1f6
+False
+
+said get a board for the green ladder & 3f9 / 8af [ < 1f6 ] / 81e < 1f6
+True
+
+said get a blue board & 3f9 / 8af [ < 1f6 ]
+False
+
+said get up & ( 3f8 , 3f9 ) [ < ( 142 , 143 ) ]
+True
+
+said get left & ( 3f8 , 3f9 ) [ < ( 142 , 143 ) ]
+False
+
+said look down & ( 3f8 , 3f9 ) [ < ( 142 , 143 ) ]
+True
+
+said get & ( 3f8 , 3f9 ) [ < ( 142 , 143 ) ]
+True
+
+said put washer on shaft & 455 , ( 3fa < cb ) / 8c6
+True
+
+said depth correct & [!*] < 8b1 / 22
+True
+
+said depth acknowledged & / 46d , 460 , 44d < 8b1
+True
+
+said depth confirmed & / 46d , 460 , 44d < 8b1
+True
+
+said depth attained & / 46d , 460 , 44d < 8b1
+True
+
+
+*/
+
+
- 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 cbb2ff3e62..0000000000
--- a/engines/sci/parser/said.y
+++ /dev/null
@@ -1,839 +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;
- Vocabulary *voc = g_sci->getVocabulary();
-
- parse_tree_node_t *parse_tree_ptr = voc->_parserNodes;
-
- if (voc->parserIsValid) {
- if (said_parse_spec(spec)) {
- printf("Offending spec was: ");
- 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 4818428663..4bf26ff0bf 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -26,8 +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 {
@@ -105,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;
@@ -143,7 +195,7 @@ Resource::Resource() {
Resource::~Resource() {
delete[] data;
- if (_source && _source->source_type == kSourcePatch)
+ if (_source && _source->getSourceType() == kSourcePatch)
delete _source;
}
@@ -154,102 +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, int volume_nr) {
- ResourceSource *newsrc = new ResourceSource();
+MacResourceForkResourceSource::~MacResourceForkResourceSource() {
+ delete _macResMan;
+}
- newsrc->source_type = kSourceExtMap;
- newsrc->location_name = mapFile->getName();
- newsrc->resourceFile = mapFile;
- newsrc->scanned = false;
- newsrc->associated_map = NULL;
- newsrc->volume_number = volume_nr;
+//-- resMan helper functions --
+
+// Resource source list management
+
+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->resourceFile = 0;
- 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;
}
@@ -258,7 +284,9 @@ ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) {
// Resource manager constructors and operations
-bool ResourceManager::loadPatch(Resource *res, Common::SeekableReadStream *file) {
+bool Resource::loadPatch(Common::SeekableReadStream *file) {
+ Resource *res = this;
+
// 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)
@@ -286,27 +314,27 @@ bool ResourceManager::loadPatch(Resource *res, Common::SeekableReadStream *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);
+ return loadPatch(&file);
}
Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *source) {
Common::List<Common::File *>::iterator it = _volumeFiles.begin();
Common::File *file;
- if (source->resourceFile)
- return source->resourceFile->createReadStream();
+ if (source->_resourceFile)
+ return source->_resourceFile->createReadStream();
- const char *filename = source->location_name.c_str();
+ const char *filename = source->getLocationName().c_str();
// check if file is already opened
while (it != _volumeFiles.end()) {
@@ -340,107 +368,131 @@ Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *sourc
static uint32 resTypeToMacTag(ResourceType type);
void ResourceManager::loadResource(Resource *res) {
- if (res->_source->source_type == kSourcePatch && loadFromPatchFile(res))
- return;
+ res->_source->loadResource(this, res);
+}
- if (res->_source->source_type == kSourceMacResourceFork) {
- Common::SeekableReadStream *stream = res->_source->macResMan.getResource(resTypeToMacTag(res->_id.type), res->_id.number);
- if (!stream)
- error("Could not get Mac resource fork resource: %d %d", res->_id.type, res->_id.number);
+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);
+ }
+}
- 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]);
- res->unalloc();
- }
- return;
+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: %s %d", getResourceTypeName(res->getType()), res->getNumber());
+
+ 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 *fileStream = getVolumeFile(res->_source);
+Common::SeekableReadStream *ResourceSource::getVolumeFile(ResourceManager *resMan, Resource *res) {
+ Common::SeekableReadStream *fileStream = resMan->getVolumeFile(this);
if (!fileStream) {
- warning("Failed to open %s", res->_source->location_name.c_str());
- res->unalloc();
- return;
+ warning("Failed to open %s", getLocationName().c_str());
+ if (res)
+ res->unalloc();
}
- switch(res->_source->source_type) {
- case kSourceWave:
- fileStream->seek(res->_fileOffset, SEEK_SET);
- loadFromWaveFile(res, fileStream);
- if (res->_source->resourceFile)
- delete fileStream;
+ return fileStream;
+}
+
+void WaveResourceSource::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;
- }
+ 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;
+
+ 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");
- fileStream->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, fileStream);
- if (res->_source->resourceFile)
- delete fileStream;
- return;
- default:
break;
}
- } else {
- // original file, directly seek to given offset and get SCI1/SCI1.1 audio resource
- fileStream->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, fileStream);
- else
- loadFromAudioVolumeSCI11(res, fileStream);
+ } 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 (res->_source->resourceFile)
- delete fileStream;
- return;
+ if (_resourceFile)
+ delete fileStream;
+}
- default:
- fileStream->seek(res->_fileOffset, SEEK_SET);
- int error = decompress(res, fileStream);
+void ResourceSource::loadResource(ResourceManager *resMan, Resource *res) {
+ Common::SeekableReadStream *fileStream = getVolumeFile(resMan, res);
+ if (!fileStream)
+ return;
- if (res->_source->resourceFile)
- delete fileStream;
+ fileStream->seek(res->_fileOffset, SEEK_SET);
- 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();
- }
+ 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) {
@@ -461,12 +513,12 @@ int ResourceManager::addAppropriateSources() {
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);
+ addSource(new VolumeResourceSource("resource.alt", addExternalMap("alt.map", 10), 10));
#endif
} else if (Common::File::exists("Data1")) {
// Mac SCI1.1+ file naming scheme
@@ -474,18 +526,19 @@ int ResourceManager::addAppropriateSources() {
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;
@@ -505,7 +558,7 @@ 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;
}
}
@@ -514,7 +567,7 @@ int ResourceManager::addAppropriateSources() {
// SCI2.1 resource patches
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
@@ -523,8 +576,12 @@ int ResourceManager::addAppropriateSources() {
#endif
addPatchDir(".");
+
if (Common::File::exists("message.map"))
- addSource(addExternalMap("message.map"), kSourceVolume, "resource.msg", 0);
+ 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;
}
@@ -568,7 +625,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) {
#ifdef ENABLE_SCI32
if (sci21PatchMap && sci21PatchRes)
- addSource(sci21PatchMap, kSourceVolume, sci21PatchRes, 100);
+ addSource(new VolumeResourceSource(sci21PatchRes->getName(), sci21PatchMap, 100, sci21PatchRes));
#endif
// Now find all the resource.0?? files
@@ -583,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));
}
}
@@ -598,16 +655,17 @@ 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;
}
@@ -615,38 +673,119 @@ 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);
-#ifdef ENABLE_SCI32
- readResourcePatchesBase36(source);
-#endif
- 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;
@@ -655,13 +794,6 @@ void ResourceManager::freeResourceSources() {
}
ResourceManager::ResourceManager() {
- addAppropriateSources();
- init();
-}
-
-ResourceManager::ResourceManager(const Common::FSList &fslist) {
- addAppropriateSources(fslist);
- init();
}
void ResourceManager::init() {
@@ -716,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() {
@@ -795,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;
}
@@ -813,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();
@@ -876,7 +1023,7 @@ const char *ResourceManager::versionDescription(ResVersion version) const {
return "Version not valid";
}
-ResourceManager::ResVersion ResourceManager::detectMapVersion() {
+ResVersion ResourceManager::detectMapVersion() {
Common::SeekableReadStream *fileStream = 0;
byte buff[6];
ResourceSource *rsrc= 0;
@@ -884,17 +1031,17 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() {
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 {
Common::File *file = new Common::File();
- file->open(rsrc->location_name);
+ file->open(rsrc->getLocationName());
if (file->isOpen())
fileStream = file;
}
break;
- } else if (rsrc->source_type == kSourceMacResourceFork)
+ } else if (rsrc->getSourceType() == kSourceMacResourceFork)
return kResVersionSci11Mac;
}
@@ -909,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;
@@ -966,24 +1113,24 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() {
return kResVersionUnknown;
}
-ResourceManager::ResVersion ResourceManager::detectVolVersion() {
+ResVersion ResourceManager::detectVolVersion() {
Common::SeekableReadStream *fileStream = 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 {
Common::File *file = new Common::File();
- file->open(rsrc->location_name);
+ file->open(rsrc->getLocationName());
if (file->isOpen())
fileStream = file;
}
break;
- } else if (rsrc->source_type == kSourceMacResourceFork)
+ } else if (rsrc->getSourceType() == kSourceMacResourceFork)
return kResVersionSci11Mac;
}
@@ -1066,83 +1213,79 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() {
}
// version-agnostic patch application
-void ResourceManager::processPatch(ResourceSource *source, ResourceType restype, uint16 resnumber, uint32 tuple) {
+void ResourceManager::processPatch(ResourceSource *source, ResourceType resourceType, uint16 resourceNr, uint32 tuple) {
Common::SeekableReadStream *fileStream = 0;
- Resource *newrsc;
- ResourceId resId = ResourceId(restype, resnumber, tuple);
- byte patchtype, patch_data_offset;
- int fsize;
-
- if (resnumber == 0xFFFF)
- return;
-
- if (source->resourceFile) {
- fileStream = source->resourceFile->createReadStream();
+ 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->location_name)) {
- warning("ResourceManager::processPatch(): failed to open %s", source->location_name.c_str());
+ if (!file->open(source->getLocationName())) {
+ warning("ResourceManager::processPatch(): failed to open %s", source->getLocationName().c_str());
return;
}
fileStream = file;
}
- fsize = fileStream->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 = fileStream->readByte() & 0x7F;
- patch_data_offset = fileStream->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:
- patch_data_offset = 8;
+ patchDataOffset = 8;
break;
default:
- warning("Resource patch unsupported special case %X", patch_data_offset & 0x7F);
+ 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());
-}
-#ifdef ENABLE_SCI32
-void ResourceManager::readResourcePatchesBase36(ResourceSource *source) {
+ 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
@@ -1156,9 +1299,11 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) {
Common::String name, inputName;
Common::ArchiveMemberList files;
- //ResourceSource *psrcPatch;
+ ResourceSource *psrcPatch;
for (int i = kResourceTypeAudio36; i <= kResourceTypeSync36; ++i) {
+ files.clear();
+
// audio36 resources start with a @, A, or B
// sync36 resources start with a #
if (i == kResourceTypeAudio36) {
@@ -1170,48 +1315,76 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) {
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 number, byte noun, byte verb, byte cond, byte seq
- // TODO: this is still not right (especially the tuple part, seems to be overflowing?)
- uint16 number = strtol(Common::String(inputName.c_str(), 2).c_str(), 0, 36);
- uint32 tuple = strtol(inputName.c_str() + 2, 0, 36);
- ResourceId resource36((ResourceType)i, number, tuple);
-
- if (i == kResourceTypeAudio36)
- debug("audio36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), tuple, resource36.toString().c_str());
- else
- debug("sync36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), tuple, resource36.toString().c_str());
-
- /*
- psrcPatch = new ResourceSource;
- psrcPatch->source_type = kSourcePatch;
- psrcPatch->location_name = name;
- psrcPatch->resourceFile = 0;
- processPatch(psrcPatch, (ResourceType)i, number, tuple);
- */
+ // 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());
+ }
}
}
}
-#endif
-
-void ResourceManager::readResourcePatches(ResourceSource *source) {
+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 <= kResourceTypeHeap; ++i) {
+ 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();
szResType = getResourceTypeName((ResourceType)i);
// SCI0 naming - type.nnn
@@ -1220,32 +1393,31 @@ 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;
- psrcPatch->resourceFile = 0;
- processPatch(psrcPatch, (ResourceType)i, number);
+ psrcPatch = new PatchResourceSource(name);
+ processPatch(psrcPatch, (ResourceType)i, resourceNr);
}
}
}
@@ -1253,18 +1425,17 @@ void ResourceManager::readResourcePatches(ResourceSource *source) {
int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
Common::SeekableReadStream *fileStream = 0;
- Resource *res;
ResourceType type;
uint16 number, id;
uint32 offset;
- if (map->resourceFile) {
- fileStream = map->resourceFile->createReadStream();
+ 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->location_name))
+ if (!file->open(map->getLocationName()))
return SCI_ERROR_RESMAP_NOT_FOUND;
fileStream = file;
}
@@ -1280,20 +1451,19 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
if (fileStream->eos() || fileStream->err()) {
delete fileStream;
- warning("Error while reading %s", map->location_name.c_str());
+ 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");
@@ -1301,12 +1471,11 @@ 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 (!fileStream->eos());
@@ -1316,15 +1485,14 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
Common::SeekableReadStream *fileStream = 0;
- Resource *res;
- if (map->resourceFile) {
- fileStream = map->resourceFile->createReadStream();
+ 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->location_name))
+ if (!file->open(map->getLocationName()))
return SCI_ERROR_RESMAP_NOT_FOUND;
fileStream = file;
}
@@ -1371,22 +1539,23 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) {
}
if (fileStream->eos() || fileStream->err()) {
delete fileStream;
- warning("Error while reading %s", map->location_name.c_str());
+ 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
// 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);
}
}
}
@@ -1427,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;
@@ -1446,11 +1615,11 @@ 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++) {
// Get the size of the file
- Common::SeekableReadStream *stream = source->macResMan.getResource(tagArray[i], idArray[j]);
+ Common::SeekableReadStream *stream = _macResMan->getResource(tagArray[i], idArray[j]);
// Some IBIS resources have a size of 0, so we skip them
if (!stream)
@@ -1461,41 +1630,44 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) {
ResourceId resId = ResourceId(type, idArray[j]);
- Resource *newrsc = NULL;
-
- // 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);
-
- // Overwrite everything
- newrsc->_id = resId;
- newrsc->_status = kResStatusNoMalloc;
- newrsc->_source = source;
- newrsc->size = fileSize;
- newrsc->_headerSize = 0;
+ // 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;
}
}
-int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream *file,
- uint32&szPacked, ResourceCompression &compression) {
+Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src, uint32 size) {
+ // Update a patched resource, whether it exists or not
+ Resource *res = 0;
+
+ if (_resMap.contains(resId)) {
+ res = _resMap.getVal(resId);
+ } else {
+ res = new Resource(this, resId);
+ _resMap.setVal(resId, res);
+ }
+
+ res->_status = kResStatusNoMalloc;
+ res->_source = src;
+ res->_headerSize = 0;
+ res->size = size;
+
+ return res;
+}
+
+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
@@ -1504,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();
@@ -1531,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();
@@ -1554,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) {
@@ -1591,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;
@@ -1625,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() {
@@ -1650,7 +1822,7 @@ ResourceCompression ResourceManager::getViewCompression() {
if (!res)
continue;
- if (res->_source->source_type != kSourceVolume)
+ if (res->_source->getSourceType() != kSourceVolume)
continue;
fileStream = getVolumeFile(res->_source);
@@ -1662,13 +1834,13 @@ ResourceCompression ResourceManager::getViewCompression() {
uint32 szPacked;
ResourceCompression compression;
- if (readResourceInfo(res, fileStream, szPacked, compression)) {
- if (res->_source->resourceFile)
+ if (res->readResourceInfo(_volVersion, fileStream, szPacked, compression)) {
+ if (res->_source->_resourceFile)
delete fileStream;
continue;
}
- if (res->_source->resourceFile)
+ if (res->_source->_resourceFile)
delete fileStream;
if (compression != kCompNone)
@@ -1686,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
@@ -1741,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;
}
@@ -1826,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
@@ -1851,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;
@@ -1863,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:
@@ -1900,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");
@@ -1928,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;
}
diff --git a/engines/sci/resource.h b/engines/sci/resource.h
index 43e61eaadb..48210b835f 100644
--- a/engines/sci/resource.h
+++ b/engines/sci/resource.h
@@ -23,22 +23,23 @@
*
*/
-#ifndef SCI_SCICORE_RESOURCE_H
-#define SCI_SCICORE_RESOURCE_H
+#ifndef SCI_RESOURCE_H
+#define SCI_RESOURCE_H
-#include "common/fs.h"
-#include "common/macresman.h"
#include "common/str.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 {
@@ -73,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,
@@ -106,167 +95,221 @@ enum ResourceType {
kResourceTypeHeap,
kResourceTypeAudio36,
kResourceTypeSync36,
- kResourceTypeUnknown1, // Translation, currently unsupported
- kResourceTypeUnknown2,
+ kResourceTypeTranslation, // Currently unsupported
kResourceTypeRobot,
- kResourceTypeInvalid,
+ kResourceTypeVMD,
+ kResourceTypeChunk,
+
+ // Mac-only resources
+ kResourceTypeMacIconBarPictN, // IBIN resources (icon bar, not selected)
+ kResourceTypeMacIconBarPictS, // IBIS resources (icon bar, selected)
+ kResourceTypeMacPict, // PICT resources (inventory)
- // Mac-only resources, these resource types are self-defined
- // Numbers subject to change
- kResourceTypeMacIconBarPictN = -1, // IBIN resources (icon bar, not selected)
- kResourceTypeMacIconBarPictS = -2, // IBIS resources (icon bar, selected)
- kResourceTypeMacPict = -3 // PICT resources (inventory)
+ kResourceTypeInvalid
};
const char *getResourceTypeName(ResourceType restype);
+enum ResVersion {
+ kResVersionUnknown,
+ kResVersionSci0Sci1Early,
+ kResVersionSci1Middle,
+ kResVersionSci1Late,
+ kResVersionSci11,
+ kResVersionSci11Mac,
+ kResVersionSci32
+};
class ResourceManager;
-
-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;
-};
+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 < kResourceTypeMacPict || 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;
+ }
-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) && (_number == other._number) && (_tuple == other._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);
@@ -278,32 +321,50 @@ 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(SciGameId gameId);
+
+#ifdef ENABLE_SCI32
+ /**
+ * Parses all resources from a SCI2.1 chunk resource and adds them to the
+ * resource manager.
*/
- void addNewGMPatch(const Common::String &gameId);
+ 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
+ * 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
+ * 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
// Note: maxMemory will not be interpreted as a hard limit, only as a restriction
@@ -325,85 +386,54 @@ protected:
ResVersion _mapVersion; ///< resource.map version
/**
- * Initializes the resource manager
- */
- void init();
-
- /**
* 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::String &filename, int volume_nr = 0);
ResourceSource *addExternalMap(const Common::FSNode *mapFile, int volume_nr = 0);
/**
- * 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);
-
- /**
- * 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);
-
- /**
* 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::SeekableReadStream *getVolumeFile(ResourceSource *source);
void loadResource(Resource *res);
- bool loadPatch(Resource *res, Common::SeekableReadStream *file);
- bool loadFromPatchFile(Resource *res);
- bool loadFromWaveFile(Resource *res, Common::SeekableReadStream *file);
- bool loadFromAudioVolumeSCI1(Resource *res, Common::SeekableReadStream *file);
- bool loadFromAudioVolumeSCI11(Resource *res, Common::SeekableReadStream *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 ---*/
@@ -423,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
@@ -451,16 +474,15 @@ protected:
/**
* Reads patch files from a local directory.
*/
- void readResourcePatches(ResourceSource *source);
-#ifdef ENABLE_SCI32
- void readResourcePatchesBase36(ResourceSource *source);
-#endif
- void processPatch(ResourceSource *source, ResourceType restype, uint16 resnumber, uint32 tuple = 0);
+ 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).
@@ -491,6 +513,7 @@ public:
uint16 prio;
uint16 size;
byte *data;
+ uint16 curPos;
long time;
byte prev;
};
@@ -515,7 +538,6 @@ public:
Track *getDigitalTrack();
int getChannelFilterMask(int hardwareMask, bool wantsRhythm);
byte getInitialVoiceCount(byte channel);
- bool isChannelUsed(byte channel) const { return _channelsUsed & (1 << channel); }
private:
SciVersion _soundVersion;
@@ -523,11 +545,8 @@ private:
Track *_tracks;
Resource *_innerResource;
ResourceManager *_resMan;
- uint16 _channelsUsed;
-
- void setChannelUsed(byte channel) { _channelsUsed |= (1 << channel); }
};
} // 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
index 57efbdcb38..a25505fe47 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -25,20 +25,30 @@
// 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 {
-void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) {
- Common::SeekableReadStream *fileStream = getVolumeFile(source);
+AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, const Common::String &name, ResourceSource *map, int volNum)
+ : VolumeResourceSource(name, map, volNum, kSourceAudioVolume) {
- if (!fileStream) {
- warning("Failed to open %s", source->location_name.c_str());
+ _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();
@@ -47,13 +57,13 @@ void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) {
case MKID_BE('OGG '):
case MKID_BE('FLAC'):
// Detected a compressed audio volume
- source->audioCompressionType = compressionType;
+ _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];
- source->audioCompressionOffsetMapping = offsetMapping;
+ _audioCompressionOffsetMapping = offsetMapping;
for (int recordNo = 0; recordNo < recordCount; recordNo++) {
*offsetMapping++ = fileStream->readUint32LE();
*offsetMapping++ = fileStream->readUint32LE();
@@ -63,105 +73,124 @@ void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) {
*offsetMapping++ = fileStream->size();
}
- if (source->resourceFile)
+ if (_resourceFile)
delete fileStream;
}
-bool ResourceManager::loadFromWaveFile(Resource *res, Common::SeekableReadStream *file) {
- res->data = new byte[res->size];
+bool Resource::loadFromWaveFile(Common::SeekableReadStream *file) {
+ data = new byte[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);
+ 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);
- res->_status = kResStatusAllocated;
+ _status = kResStatusAllocated;
return true;
}
-bool ResourceManager::loadFromAudioVolumeSCI11(Resource *res, Common::SeekableReadStream *file) {
+bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) {
// Check for WAVE files here
uint32 riffTag = file->readUint32BE();
if (riffTag == MKID_BE('RIFF')) {
- res->_headerSize = 0;
- res->size = file->readUint32LE();
+ _headerSize = 0;
+ size = file->readUint32LE() + 8;
file->seek(-8, SEEK_CUR);
- return loadFromWaveFile(res, file);
+ return loadFromWaveFile(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", res->_id.toString().c_str());
- res->unalloc();
+ 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;
}
- res->_headerSize = file->readByte();
+ _headerSize = file->readByte();
if (type == kResourceTypeAudio) {
- if (res->_headerSize != 11 && res->_headerSize != 12) {
+ if (_headerSize != 7 && _headerSize != 11 && _headerSize != 12) {
warning("Unsupported audio header");
- res->unalloc();
+ 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);
+ 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(res, file);
+ return loadPatch(file);
}
-bool ResourceManager::loadFromAudioVolumeSCI1(Resource *res, Common::SeekableReadStream *file) {
- res->data = new byte[res->size];
+bool Resource::loadFromAudioVolumeSCI1(Common::SeekableReadStream *file) {
+ data = new byte[size];
- if (res->data == NULL) {
- error("Can't allocate %d bytes needed for loading %s", res->size, res->_id.toString().c_str());
+ if (data == NULL) {
+ error("Can't allocate %d bytes needed for loading %s", size, _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);
+ 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);
- res->_status = kResStatusAllocated;
+ _status = kResStatusAllocated;
return true;
}
-void ResourceManager::addNewGMPatch(const Common::String &gameId) {
+void ResourceManager::addNewGMPatch(SciGameId gameId) {
Common::String gmPatchFile;
- if (gameId == "ecoquest")
+ switch (gameId) {
+ case GID_ECOQUEST:
gmPatchFile = "ECO1GM.PAT";
- else if (gameId == "hoyle3")
- gmPatchFile = "HOY3GM.PAT";
- else if (gameId == "hoyle3")
+ break;
+ case GID_HOYLE3:
gmPatchFile = "HOY3GM.PAT";
- else if (gameId == "lsl1sci")
+ break;
+ case GID_LSL1:
gmPatchFile = "LL1_GM.PAT";
- else if (gameId == "lsl5")
+ break;
+ case GID_LSL5:
gmPatchFile = "LL5_GM.PAT";
- else if (gameId == "longbow")
+ break;
+ case GID_LONGBOW:
gmPatchFile = "ROBNGM.PAT";
- else if (gameId == "sq1sci")
+ break;
+ case GID_SQ1:
gmPatchFile = "SQ1_GM.PAT";
- else if (gameId == "sq4")
+ break;
+ case GID_SQ4:
gmPatchFile = "SQ4_GM.PAT";
- else if (gameId == "fairytales")
+ break;
+ case GID_FAIRYTALES:
gmPatchFile = "TALEGM.PAT";
+ break;
+ default:
+ break;
+ }
if (!gmPatchFile.empty() && Common::File::exists(gmPatchFile)) {
- ResourceSource *psrcPatch = new ResourceSource;
- psrcPatch->source_type = kSourcePatch;
- psrcPatch->resourceFile = 0;
- psrcPatch->location_name = 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;
@@ -170,39 +199,8 @@ void ResourceManager::readWaveAudioPatches() {
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->resourceFile = 0;
- 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());
- }
+ if (isdigit(name[0]))
+ processWavePatch(ResourceId(kResourceTypeAudio, atoi(name.c_str())), name);
}
}
@@ -211,7 +209,7 @@ void ResourceManager::removeAudioResource(ResourceId resId) {
if (_resMap.contains(resId)) {
Resource *res = _resMap.getVal(resId);
- if (res->_source->source_type == kSourceAudioVolume) {
+ if (res->_source->getSourceType() == kSourceAudioVolume) {
if (res->_status == kResStatusLocked) {
warning("Failed to remove resource %s (still in use)", resId.toString().c_str());
} else {
@@ -237,6 +235,20 @@ void ResourceManager::removeAudioResource(ResourceId resId) {
// 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:
@@ -261,27 +273,31 @@ void ResourceManager::removeAudioResource(ResourceId resId) {
// 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);
+ Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->_volumeNumber), false);
if (!mapRes) {
- warning("Failed to open %i.MAP", map->volume_number);
+ warning("Failed to open %i.MAP", map->_volumeNumber);
return SCI_ERROR_RESMAP_NOT_FOUND;
}
- ResourceSource *src = getVolume(map, 0);
+ ResourceSource *src = findVolume(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;
+ // 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;
@@ -289,7 +305,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) {
if (n == 0xffff)
break;
- if (isEarly) {
+ if (entrySize == 6) {
offset = READ_LE_UINT32(ptr);
ptr += 4;
} else {
@@ -299,10 +315,50 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) {
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 {
- // Heuristic to detect late SCI1.1 map format
- if ((mapRes->size >= 11) && (ptr[mapRes->size - 11] == 0xff))
- isEarly = false;
+ bool isEarly = (entrySize != 11);
if (!isEarly) {
offset = READ_LE_UINT32(ptr);
@@ -330,15 +386,17 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) {
ptr += 2;
if (syncSize > 0)
- addResource(ResourceId(kResourceTypeSync36, map->volume_number, n & 0xffffff3f), src, offset, syncSize);
+ 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->volume_number, n & 0xffffff3f), src, offset + syncSize);
+ addResource(ResourceId(kResourceTypeAudio36, map->_volumeNumber, n & 0xffffff3f), src, offset + syncSize);
}
}
@@ -358,7 +416,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) {
int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) {
Common::File file;
- if (!file.open(map->location_name))
+ if (!file.open(map->getLocationName()))
return SCI_ERROR_RESMAP_NOT_FOUND;
bool oldFormat = (file.readUint16LE() >> 11) == kResourceTypeAudio;
@@ -370,7 +428,7 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) {
uint32 size = file.readUint32LE();
if (file.eos() || file.err()) {
- warning("Error while reading %s", map->location_name.c_str());
+ warning("Error while reading %s", map->getLocationName().c_str());
return SCI_ERROR_RESMAP_NOT_FOUND;
}
@@ -388,7 +446,7 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) {
offset &= 0x0fffffff; // least significant 28 bits
}
- ResourceSource *src = getVolume(map, volume_nr);
+ ResourceSource *src = findVolume(map, volume_nr);
if (src) {
if (unload)
@@ -405,7 +463,7 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) {
void ResourceManager::setAudioLanguage(int language) {
if (_audioMapSCI1) {
- if (_audioMapSCI1->volume_number == language) {
+ if (_audioMapSCI1->_volumeNumber == language) {
// This language is already loaded
return;
}
@@ -417,7 +475,7 @@ void ResourceManager::setAudioLanguage(int language) {
Common::List<ResourceSource *>::iterator it = _sources.begin();
while (it != _sources.end()) {
ResourceSource *src = *it;
- if (src->associated_map == _audioMapSCI1) {
+ if (src->findVolume(_audioMapSCI1, src->_volumeNumber)) {
it = _sources.erase(it);
delete src;
} else {
@@ -441,7 +499,7 @@ void ResourceManager::setAudioLanguage(int language) {
return;
}
- _audioMapSCI1 = addSource(NULL, kSourceExtAudioMap, fullname.c_str(), language);
+ _audioMapSCI1 = addSource(new ExtAudioMapResourceSource(fullname, language));
// Search for audio volumes for this language and add them to the source list
Common::ArchiveMemberList files;
@@ -451,18 +509,18 @@ void ResourceManager::setAudioLanguage(int language) {
const char *dot = strrchr(name.c_str(), '.');
int number = atoi(dot + 1);
- addSource(_audioMapSCI1, kSourceAudioVolume, name.c_str(), number);
+ addSource(new AudioVolumeResourceSource(this, name, _audioMapSCI1, number));
}
scanNewSources();
}
int ResourceManager::getAudioLanguage() const {
- return (_audioMapSCI1 ? _audioMapSCI1->volume_number : 0);
+ return (_audioMapSCI1 ? _audioMapSCI1->_volumeNumber : 0);
}
-SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) {
- Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true);
+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;
@@ -473,8 +531,6 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi
byte *dataEnd;
Channel *channel, *sampleChannel;
- _channelsUsed = 0;
-
switch (_soundVersion) {
case SCI_VERSION_0_EARLY:
case SCI_VERSION_0_LATE:
@@ -526,6 +582,7 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi
case SCI_VERSION_1_EARLY:
case SCI_VERSION_1_LATE:
+ case SCI_VERSION_2_1:
data = resource->data;
// Count # of tracks
_trackCount = 0;
@@ -537,6 +594,9 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi
}
_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
@@ -546,35 +606,47 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi
_tracks[trackNr].type = *data++;
// Counting # of channels used
data2 = data;
- _tracks[trackNr].channelCount = 0;
+ channelCount = 0;
while (*data2 != 0xFF) {
data2 += 6;
+ channelCount++;
_tracks[trackNr].channelCount++;
}
- _tracks[trackNr].channels = new Channel[_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
- for (channelNr = 0; channelNr < _tracks[trackNr].channelCount; channelNr++) {
+ channelNr = 0;
+ while (channelCount--) {
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);
- setChannelUsed(channel->number);
- 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;
+ 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;
}
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 929bdf3307..d0c578bd45 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,22 +38,33 @@
#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 {
@@ -61,13 +74,23 @@ 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");
@@ -78,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");
@@ -91,26 +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;
- _gfxMacIconBar = 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,183 +141,349 @@ 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 and SCI01 games used a parser
+ _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan, false) : NULL;
+ _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();
- if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1)
- _gfxMacIconBar = new GfxMacIconBar();
+ // Initialize all graphics related subsystems
+ initGraphics();
- GfxPalette *palette = new GfxPalette(_resMan, screen);
- GfxCache *cache = new GfxCache(_resMan, screen, palette);
- GfxCursor *cursor = new GfxCursor(_resMan, palette, screen);
+ debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()));
- // Create debugger console. It requires GFX to be initialized
- _console = new Console(this);
+ 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);
+ }
+ }
- _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);
+ // 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;
+ }
+ }
- _features = new GameFeatures(segMan, _kernel);
+ runGame();
- _gamestate = new EngineState(segMan);
+ ConfMan.flushToDisk();
- _gamestate->_event = new SciEvent(_resMan);
+ return Common::kNoError;
+}
- if (script_init_engine(_gamestate))
- return Common::kUnknownError;
+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);
-#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;
+ _gamestate->_msgState = new MessageState(_gamestate->_segMan);
+ _gamestate->gcCountDown = GC_INTERVAL - 1;
+
+ // Script 0 should always be at segment 1
+ if (script0Segment != 1) {
+ debug(2, "Failed to instantiate script.000");
+ return false;
}
-#endif
- _gfxPalette = palette;
- _gfxScreen = screen;
- _gfxCache = cache;
- _gfxCursor = cursor;
+ _gamestate->initGlobals();
+ _gamestate->_segMan->initSysStrings();
- if (game_init(_gamestate)) { /* Initialize */
- warning("Game initialization failed: Aborting...");
- // TODO: Add an "init failed" error?
- return Common::kUnknownError;
+ _gamestate->r_acc = _gamestate->r_prev = NULL_REG;
+
+ _gamestate->_executionStack.clear(); // Start without any execution stack
+ _gamestate->executionStackBase = -1; // No vm is running yet
+ _gamestate->_executionStackPosChanged = false;
+
+ _gamestate->abortScriptProcessing = kAbortNone;
+ _gamestate->gameIsRestarting = GAMEISRESTARTING_NONE;
+
+ _gamestate->stack_base = stack->_entries;
+ _gamestate->stack_top = stack->_entries + stack->_capacity;
+
+ if (!_gamestate->_segMan->instantiateScript(0)) {
+ error("initGame(): Could not instantiate script 0");
+ return false;
}
- // Add the after market GM patches for the specified game, if they exist
- _resMan->addNewGMPatch(getGameID());
+ // Reset parser
+ if (_vocabulary) {
+ _vocabulary->reset();
+ }
- script_adjust_opcode_formats(_gamestate);
- _kernel->loadKernelNames(getGameID());
+ _gamestate->gameStartTime = _gamestate->lastWaitTime = _gamestate->_screenUpdateTime = g_system->getMillis();
- SciVersion soundVersion = _features->detectDoSoundType();
+ // Load game language into printLang property of game object
+ setSciLanguage();
- _gamestate->_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, soundVersion);
+ return true;
+}
- screen->debugUnditherSetState(ConfMan.getBool("undither"));
+void SciEngine::initGraphics() {
-#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 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
+ _gfxFrameout = 0;
+ _gfxPaint32 = 0;
#endif
- syncSoundSettings();
+ if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1)
+ _gfxMacIconBar = new GfxMacIconBar();
+
+ 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 (_gui32)
- _gui32->init();
- else
+ 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 {
+#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
- _gui->init(_features->usesOldGfxFunctions());
- debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()));
+ if (_gfxPorts) {
+ _gfxPorts->init(_features->usesOldGfxFunctions(), _gfxPaint16, _gfxText16);
+ _gfxPaint16->init(_gfxAnimate, _gfxText16);
+ }
+ // Set default (EGA, amiga or resource 999) palette
+ _gfxPalette->setDefault();
+}
- // Check whether loading a savestate was requested
- if (ConfMan.hasKey("save_slot")) {
- _gamestate->loadFromLauncher = ConfMan.getInt("save_slot");
- } else {
- _gamestate->loadFromLauncher = -1;
+void SciEngine::initStackBaseWithSelector(Selector selector) {
+ _gamestate->stack_base[0] = make_reg(0, (uint16)selector);
+ _gamestate->stack_base[1] = NULL_REG;
+
+ // 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");
}
- game_run(&_gamestate); // Run the game
+}
- game_exit(_gamestate);
+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);
+}
- ConfMan.flushToDisk();
+void SciEngine::exitGame() {
+ if (_gamestate->abortScriptProcessing != kAbortLoadGame) {
+ _gamestate->_executionStack.clear();
+ _audio->stopAllAudio();
+ g_sci->_soundCmd->clearPlayList();
+ }
- 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;
+ // TODO Free parser segment here
- return Common::kNoError;
+ // 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;
}
@@ -304,7 +493,7 @@ Console *SciEngine::getSciDebugger() {
return _console;
}
-const char* SciEngine::getGameID() const {
+const char *SciEngine::getGameIdStr() const {
return _gameDescription->gameid;
}
@@ -316,12 +505,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 {
@@ -333,19 +518,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;
}
@@ -361,27 +547,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 685f05e685..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 GfxMacIconBar;
+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,27 +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 7748c0505b..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;
}
@@ -239,9 +274,11 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
// 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);
@@ -271,7 +308,7 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32
// 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);
}
@@ -287,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;
@@ -318,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;
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/iterator/core.cpp b/engines/sci/sound/iterator/core.cpp
deleted file mode 100644
index 7cd730b3e2..0000000000
--- a/engines/sci/sound/iterator/core.cpp
+++ /dev/null
@@ -1,1013 +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$
- *
- */
-
-/* Sound subsystem core: Event handler, sound player dispatching */
-
-#include "sci/sci.h"
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-
-#include "sci/sound/iterator/core.h"
-#include "sci/sound/iterator/iterator.h"
-#include "sci/sound/drivers/mididriver.h"
-
-#include "common/system.h"
-#include "common/timer.h"
-
-#include "sound/mixer.h"
-
-namespace Sci {
-
-/* Plays a song iterator that found a PCM through a PCM device, if possible
-** Parameters: (SongIterator *) it: The iterator to play
-** (SongHandle) handle: Debug handle
-** Returns : (int) 0 if the effect will not be played, nonzero if it will
-** This assumes that the last call to 'it->next()' returned SI_PCM.
-*/
-static int sfx_play_iterator_pcm(SongIterator *it, SongHandle handle);
-
-
-#pragma mark -
-
-
-class SfxPlayer {
-public:
- /** Number of voices that can play simultaneously */
- int _polyphony;
-
-protected:
- SciVersion _soundVersion;
- MidiPlayer *_mididrv;
-
- SongIterator *_iterator;
- Audio::Timestamp _wakeupTime;
- Audio::Timestamp _currentTime;
- uint32 _pauseTimeDiff;
-
- bool _paused;
- bool _iteratorIsDone;
- uint32 _tempo;
-
- Common::Mutex _mutex;
- int _volume;
-
- void play_song(SongIterator *it);
- static void player_timer_callback(void *refCon);
-
-public:
- SfxPlayer(SciVersion soundVersion);
- ~SfxPlayer();
-
- /**
- * Initializes the player.
- * @param resMan a resource manager for driver initialization
- * @param expected_latency expected delay in between calls to 'maintenance' (in microseconds)
- * @return Common::kNoError on success, Common::kUnknownError on failure
- */
- Common::Error init(ResourceManager *resMan, int expected_latency);
-
- /**
- * Adds an iterator to the song player
- * @param it The iterator to play
- * @param start_time The time to assume as the time the first MIDI command executes at
- * @return Common::kNoError on success, Common::kUnknownError on failure
- *
- * The iterator should not be cloned (to avoid memory leaks) and
- * may be modified according to the needs of the player.
- * Implementors may use the 'sfx_iterator_combine()' function
- * to add iterators onto their already existing iterators.
- */
- Common::Error add_iterator(SongIterator *it, uint32 start_time);
-
- /**
- * Stops the currently playing song and deletes the associated iterator.
- * @return Common::kNoError on success, Common::kUnknownError on failure
- */
- Common::Error stop();
-
- /**
- * Transmits a song iterator message to the active song.
- * @param msg the message to transmit
- * @return Common::kNoError on success, Common::kUnknownError on failure
- */
- Common::Error iterator_message(const SongIterator::Message &msg);
-
- /**
- * Pauses song playing.
- * @return Common::kNoError on success, Common::kUnknownError on failure
- */
- Common::Error pause();
-
- /**
- * Resumes song playing after a pause.
- * @return Common::kNoError on success, Common::kUnknownError on failure
- */
- Common::Error resume();
-
- /**
- * Pass a raw MIDI event to the synth.
- * @param argc length of buffer holding the midi event
- * @param argv the buffer itself
- */
- void tell_synth(int buf_nr, byte *buf);
-
- void setVolume(int vol);
-
- int getVolume();
-};
-
-SfxPlayer::SfxPlayer(SciVersion soundVersion)
- : _soundVersion(soundVersion), _wakeupTime(0, SFX_TICKS_PER_SEC), _currentTime(0, 1) {
- _polyphony = 0;
-
- _mididrv = 0;
-
- _iterator = NULL;
- _pauseTimeDiff = 0;
-
- _paused = false;
- _iteratorIsDone = false;
- _tempo = 0;
-
- _volume = 15;
-}
-
-SfxPlayer::~SfxPlayer() {
- if (_mididrv) {
- _mididrv->close();
- delete _mididrv;
- }
- delete _iterator;
- _iterator = NULL;
-}
-
-void SfxPlayer::play_song(SongIterator *it) {
- while (_iterator && _wakeupTime.msecsDiff(_currentTime) <= 0) {
- int delay;
- byte buf[8];
- int result;
-
- switch ((delay = songit_next(&(_iterator),
- buf, &result,
- IT_READER_MASK_ALL
- | IT_READER_MAY_FREE
- | IT_READER_MAY_CLEAN))) {
-
- case SI_FINISHED:
- delete _iterator;
- _iterator = NULL;
- _iteratorIsDone = true;
- return;
-
- case SI_IGNORE:
- case SI_LOOP:
- case SI_RELATIVE_CUE:
- case SI_ABSOLUTE_CUE:
- break;
-
- case SI_PCM:
- sfx_play_iterator_pcm(_iterator, 0);
- break;
-
- case 0:
- static_cast<MidiDriver *>(_mididrv)->send(buf[0], buf[1], buf[2]);
-
- break;
-
- default:
- _wakeupTime = _wakeupTime.addFrames(delay);
- }
- }
-}
-
-void SfxPlayer::tell_synth(int buf_nr, byte *buf) {
- byte op1 = (buf_nr < 2 ? 0 : buf[1]);
- byte op2 = (buf_nr < 3 ? 0 : buf[2]);
-
- static_cast<MidiDriver *>(_mididrv)->send(buf[0], op1, op2);
-}
-
-void SfxPlayer::player_timer_callback(void *refCon) {
- SfxPlayer *thePlayer = (SfxPlayer *)refCon;
- assert(refCon);
- Common::StackLock lock(thePlayer->_mutex);
-
- if (thePlayer->_iterator && !thePlayer->_iteratorIsDone && !thePlayer->_paused) {
- thePlayer->play_song(thePlayer->_iterator);
- }
-
- thePlayer->_currentTime = thePlayer->_currentTime.addFrames(1);
-}
-
-/* API implementation */
-
-Common::Error SfxPlayer::init(ResourceManager *resMan, int expected_latency) {
- MidiDriverType musicDriver = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB);
-
- switch (musicDriver) {
- case MD_ADLIB:
- // FIXME: There's no Amiga sound option, so we hook it up to AdLib
- if (g_sci->getPlatform() == Common::kPlatformAmiga)
- _mididrv = MidiPlayer_Amiga_create(_soundVersion);
- else
- _mididrv = MidiPlayer_AdLib_create(_soundVersion);
- break;
- case MD_PCJR:
- _mididrv = MidiPlayer_PCJr_create(_soundVersion);
- break;
- case MD_PCSPK:
- _mididrv = MidiPlayer_PCSpeaker_create(_soundVersion);
- break;
- default:
- break;
- }
-
- assert(_mididrv);
-
- _polyphony = _mididrv->getPolyphony();
-
- _tempo = _mididrv->getBaseTempo();
- uint32 time = g_system->getMillis();
- _currentTime = Audio::Timestamp(time, 1000000 / _tempo);
- _wakeupTime = Audio::Timestamp(time, SFX_TICKS_PER_SEC);
-
- _mididrv->setTimerCallback(this, player_timer_callback);
- _mididrv->open(resMan);
- _mididrv->setVolume(_volume);
-
- return Common::kNoError;
-}
-
-Common::Error SfxPlayer::add_iterator(SongIterator *it, uint32 start_time) {
- Common::StackLock lock(_mutex);
- SIMSG_SEND(it, SIMSG_SET_PLAYMASK(_mididrv->getPlayId()));
- SIMSG_SEND(it, SIMSG_SET_RHYTHM(_mididrv->hasRhythmChannel()));
-
- if (_iterator == NULL) {
- // Resync with clock
- _currentTime = Audio::Timestamp(g_system->getMillis(), 1000000 / _tempo);
- _wakeupTime = Audio::Timestamp(start_time, SFX_TICKS_PER_SEC);
- }
-
- _iterator = sfx_iterator_combine(_iterator, it);
- _iteratorIsDone = false;
-
- return Common::kNoError;
-}
-
-Common::Error SfxPlayer::stop() {
- debug(3, "Player: Stopping song iterator %p", (void *)_iterator);
- Common::StackLock lock(_mutex);
- delete _iterator;
- _iterator = NULL;
- for (int i = 0; i < MIDI_CHANNELS; i++)
- static_cast<MidiDriver *>(_mididrv)->send(0xb0 + i, SCI_MIDI_CHANNEL_NOTES_OFF, 0);
-
- return Common::kNoError;
-}
-
-Common::Error SfxPlayer::iterator_message(const SongIterator::Message &msg) {
- Common::StackLock lock(_mutex);
- if (!_iterator) {
- return Common::kUnknownError;
- }
-
- songit_handle_message(&_iterator, msg);
-
- return Common::kNoError;
-}
-
-Common::Error SfxPlayer::pause() {
- Common::StackLock lock(_mutex);
-
- _paused = true;
- _pauseTimeDiff = _wakeupTime.msecsDiff(_currentTime);
-
- _mididrv->playSwitch(false);
-
- return Common::kNoError;
-}
-
-Common::Error SfxPlayer::resume() {
- Common::StackLock lock(_mutex);
-
- _wakeupTime = Audio::Timestamp(_currentTime.msecs() + _pauseTimeDiff, SFX_TICKS_PER_SEC);
- _mididrv->playSwitch(true);
- _paused = false;
-
- return Common::kNoError;
-}
-
-void SfxPlayer::setVolume(int vol) {
- _mididrv->setVolume(vol);
-}
-
-int SfxPlayer::getVolume() {
- return _mididrv->getVolume();
-}
-
-#pragma mark -
-
-void SfxState::sfx_reset_player() {
- if (_player)
- _player->stop();
-}
-
-void SfxState::sfx_player_tell_synth(int buf_nr, byte *buf) {
- if (_player)
- _player->tell_synth(buf_nr, buf);
-}
-
-int SfxState::sfx_get_player_polyphony() {
- if (_player)
- return _player->_polyphony;
- else
- return 0;
-}
-
-SfxState::SfxState() {
- _player = NULL;
- _it = NULL;
- _flags = 0;
- _song = NULL;
- _suspended = 0;
-}
-
-SfxState::~SfxState() {
-}
-
-
-void SfxState::freezeTime() {
- /* Freezes the top song delay time */
- const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC);
- Song *song = _song;
-
- while (song) {
- song->_delay = song->_wakeupTime.frameDiff(ctime);
- if (song->_delay < 0)
- song->_delay = 0;
-
- song = song->_nextPlaying;
- }
-}
-
-void SfxState::thawTime() {
- /* inverse of freezeTime() */
- const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC);
- Song *song = _song;
-
- while (song) {
- song->_wakeupTime = ctime.addFrames(song->_delay);
-
- song = song->_nextPlaying;
- }
-}
-
-#if 0
-// Unreferenced - removed
-static void _dump_playing_list(SfxState *self, char *msg) {
- Song *song = self->_song;
-
- fprintf(stderr, "[] Song list : [ ");
- song = *(self->_songlib.lib);
- while (song) {
- fprintf(stderr, "%08lx:%d ", song->handle, song->_status);
- song = song->_nextPlaying;
- }
- fprintf(stderr, "]\n");
-
- fprintf(stderr, "[] Play list (%s) : [ " , msg);
-
- while (song) {
- fprintf(stderr, "%08lx ", song->handle);
- song = song->_nextPlaying;
- }
-
- fprintf(stderr, "]\n");
-}
-#endif
-
-#if 0
-static void _dump_songs(SfxState *self) {
- Song *song = self->_song;
-
- fprintf(stderr, "Cue iterators:\n");
- song = *(self->_songlib.lib);
- while (song) {
- fprintf(stderr, " **\tHandle %08x (p%d): status %d\n",
- song->handle, song->_priority, song->_status);
- SIMSG_SEND(song->_it, SIMSG_PRINT(1));
- song = song->_next;
- }
-
- if (self->_player) {
- fprintf(stderr, "Audio iterator:\n");
- self->_player->iterator_message(SongIterator::Message(0, SIMSG_PRINT(1)));
- }
-}
-#endif
-
-bool SfxState::isPlaying(Song *song) {
- Song *playing_song = _song;
-
- /* _dump_playing_list(this, "is-playing");*/
-
- while (playing_song) {
- if (playing_song == song)
- return true;
- playing_song = playing_song->_nextPlaying;
- }
- return false;
-}
-
-void SfxState::setSongStatus(Song *song, int status) {
- const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC);
-
- switch (status) {
-
- case SOUND_STATUS_STOPPED:
- // Reset
- song->_it->init();
- break;
-
- case SOUND_STATUS_SUSPENDED:
- case SOUND_STATUS_WAITING:
- if (song->_status == SOUND_STATUS_PLAYING) {
- // Update delay, set wakeup_time
- song->_delay += song->_wakeupTime.frameDiff(ctime);
- song->_wakeupTime = ctime;
- }
- if (status == SOUND_STATUS_SUSPENDED)
- break;
-
- /* otherwise... */
-
- case SOUND_STATUS_PLAYING:
- if (song->_status == SOUND_STATUS_STOPPED) {
- // Starting anew
- song->_wakeupTime = ctime;
- }
-
- if (isPlaying(song))
- status = SOUND_STATUS_PLAYING;
- else
- status = SOUND_STATUS_WAITING;
- break;
-
- default:
- fprintf(stderr, "%s L%d: Attempt to set invalid song"
- " state %d!\n", __FILE__, __LINE__, status);
- return;
-
- }
- song->_status = status;
-}
-
-/* Update internal state iff only one song may be played */
-void SfxState::updateSingleSong() {
- Song *newsong = _songlib.findFirstActive();
-
- if (newsong != _song) {
- freezeTime(); /* Store song delay time */
-
- if (_player)
- _player->stop();
-
- if (newsong) {
- if (!newsong->_it)
- return; /* Restore in progress and not ready for this yet */
-
- /* Change song */
- if (newsong->_status == SOUND_STATUS_WAITING)
- setSongStatus(newsong, SOUND_STATUS_PLAYING);
-
- /* Change instrument mappings */
- } else {
- /* Turn off sound */
- }
- if (_song) {
- if (_song->_status == SOUND_STATUS_PLAYING)
- setSongStatus(newsong, SOUND_STATUS_WAITING);
- }
-
- Common::String debugMessage = "[SFX] Changing active song:";
- if (!_song) {
- debugMessage += " New song:";
- } else {
- char tmp[50];
- sprintf(tmp, " pausing %08lx, now playing ", _song->_handle);
- debugMessage += tmp;
- }
-
- if (newsong) {
- char tmp[20];
- sprintf(tmp, "%08lx\n", newsong->_handle);
- debugMessage += tmp;
- } else {
- debugMessage += " none\n";
- }
-
- debugC(2, kDebugLevelSound, "%s", debugMessage.c_str());
-
- _song = newsong;
- thawTime(); /* Recover song delay time */
-
- if (newsong && _player) {
- SongIterator *clonesong = newsong->_it->clone(newsong->_delay);
-
- _player->add_iterator(clonesong, newsong->_wakeupTime.msecs());
- }
- }
-}
-
-
-void SfxState::updateMultiSong() {
- Song *oldfirst = _song;
- Song *oldseeker;
- Song *newsong = _songlib.findFirstActive();
- Song *newseeker;
- Song not_playing_anymore; /* Dummy object, referenced by
- ** songs which are no longer
- ** active. */
-
- /* _dump_playing_list(this, "before");*/
- freezeTime(); /* Store song delay time */
-
- // WORKAROUND: sometimes, newsong can be NULL (e.g. in SQ4).
- // Handle this here, so that we avoid a crash
- if (!newsong) {
- // Iterators should get freed when there's only one song left playing
- if(oldfirst && oldfirst->_status == SOUND_STATUS_STOPPED) {
- debugC(2, kDebugLevelSound, "[SFX] Stopping song %lx", oldfirst->_handle);
- if (_player && oldfirst->_it)
- _player->iterator_message(SongIterator::Message(oldfirst->_it->ID, SIMSG_STOP));
- }
- return;
- }
-
- for (newseeker = newsong; newseeker;
- newseeker = newseeker->_nextPlaying) {
- if (!newseeker || !newseeker->_it)
- return; /* Restore in progress and not ready for this yet */
- }
-
- /* First, put all old songs into the 'stopping' list and
- ** mark their 'next-playing' as not_playing_anymore. */
- for (oldseeker = oldfirst; oldseeker;
- oldseeker = oldseeker->_nextStopping) {
- oldseeker->_nextStopping = oldseeker->_nextPlaying;
- oldseeker->_nextPlaying = &not_playing_anymore;
-
- if (oldseeker == oldseeker->_nextPlaying) {
- error("updateMultiSong() failed. Breakpoint in %s, line %d", __FILE__, __LINE__);
- }
- }
-
- /* Second, re-generate the new song queue. */
- for (newseeker = newsong; newseeker; newseeker = newseeker->_nextPlaying) {
- newseeker->_nextPlaying = _songlib.findNextActive(newseeker);
-
- if (newseeker == newseeker->_nextPlaying) {
- error("updateMultiSong() failed. Breakpoint in %s, line %d", __FILE__, __LINE__);
- }
- }
- /* We now need to update the currently playing song list, because we're
- ** going to use some functions that require this list to be in a sane
- ** state (particularly isPlaying(), indirectly */
- _song = newsong;
-
- /* Third, stop all old songs */
- for (oldseeker = oldfirst; oldseeker;
- oldseeker = oldseeker->_nextStopping)
- if (oldseeker->_nextPlaying == &not_playing_anymore) {
- setSongStatus(oldseeker, SOUND_STATUS_SUSPENDED);
- debugC(2, kDebugLevelSound, "[SFX] Stopping song %lx", oldseeker->_handle);
-
- if (_player && oldseeker->_it)
- _player->iterator_message(SongIterator::Message(oldseeker->_it->ID, SIMSG_STOP));
- oldseeker->_nextPlaying = NULL; /* Clear this pointer; we don't need the tag anymore */
- }
-
- for (newseeker = newsong; newseeker; newseeker = newseeker->_nextPlaying) {
- if (newseeker->_status != SOUND_STATUS_PLAYING && _player) {
- debugC(2, kDebugLevelSound, "[SFX] Adding song %lx", newseeker->_it->ID);
-
- SongIterator *clonesong = newseeker->_it->clone(newseeker->_delay);
- _player->add_iterator(clonesong, g_system->getMillis());
- }
- setSongStatus(newseeker, SOUND_STATUS_PLAYING);
- }
-
- _song = newsong;
- thawTime();
- /* _dump_playing_list(this, "after");*/
-}
-
-/* Update internal state */
-void SfxState::update() {
- if (_flags & SFX_STATE_FLAG_MULTIPLAY)
- updateMultiSong();
- else
- updateSingleSong();
-}
-
-static int sfx_play_iterator_pcm(SongIterator *it, SongHandle handle) {
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Playing PCM: %08lx\n", handle);
-#endif
- if (g_system->getMixer()->isReady()) {
- Audio::AudioStream *newfeed = it->getAudioStream();
- if (newfeed) {
- g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, 0, newfeed);
- return 1;
- }
- }
- return 0;
-}
-
-#define DELAY (1000000 / SFX_TICKS_PER_SEC)
-
-void SfxState::sfx_init(ResourceManager *resMan, int flags, SciVersion soundVersion) {
- _songlib._lib = 0;
- _song = NULL;
- _flags = flags;
-
- _player = NULL;
-
- if (flags & SFX_STATE_FLAG_NOSOUND) {
- warning("[SFX] Sound disabled");
- return;
- }
-
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Initialising: flags=%x\n", flags);
-#endif
-
- /*-------------------*/
- /* Initialise player */
- /*-------------------*/
-
- if (!resMan) {
- warning("[SFX] Warning: No resource manager present, cannot initialise player");
- return;
- }
-
- _player = new SfxPlayer(soundVersion);
-
- if (!_player) {
- warning("[SFX] No song player found");
- return;
- }
-
- if (_player->init(resMan, DELAY / 1000)) {
- warning("[SFX] Song player reported error, disabled");
- delete _player;
- _player = NULL;
- }
-
- _resMan = resMan;
-}
-
-void SfxState::sfx_exit() {
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Uninitialising\n");
-#endif
-
- delete _player;
- _player = 0;
-
- g_system->getMixer()->stopAll();
-
- _songlib.freeSounds();
-}
-
-void SfxState::sfx_suspend(bool suspend) {
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Suspending? = %d\n", suspend);
-#endif
- if (suspend && (!_suspended)) {
- /* suspend */
-
- freezeTime();
- if (_player)
- _player->pause();
- /* Suspend song player */
-
- } else if (!suspend && (_suspended)) {
- /* unsuspend */
-
- thawTime();
- if (_player)
- _player->resume();
-
- /* Unsuspend song player */
- }
-
- _suspended = suspend;
-}
-
-int SfxState::sfx_poll(SongHandle *handle, int *cue) {
- if (!_song)
- return 0; /* No milk today */
-
- *handle = _song->_handle;
-
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Polling any (%08lx)\n", *handle);
-#endif
- return sfx_poll_specific(*handle, cue);
-}
-
-int SfxState::sfx_poll_specific(SongHandle handle, int *cue) {
- const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC);
- Song *song = _song;
-
- while (song && song->_handle != handle)
- song = song->_nextPlaying;
-
- if (!song)
- return 0; /* Song not playing */
-
- debugC(2, kDebugLevelSound, "[SFX:CUE] Polled song %08lx ", handle);
-
- while (1) {
- if (song->_wakeupTime.frameDiff(ctime) > 0)
- return 0; /* Patience, young hacker! */
-
- byte buf[8];
- int result = songit_next(&(song->_it), buf, cue, IT_READER_MASK_ALL);
-
- switch (result) {
-
- case SI_FINISHED:
- setSongStatus(song, SOUND_STATUS_STOPPED);
- update();
- /* ...fall through... */
- case SI_LOOP:
- case SI_RELATIVE_CUE:
- case SI_ABSOLUTE_CUE:
- if (result == SI_FINISHED)
- debugC(2, kDebugLevelSound, " => finished");
- else {
- if (result == SI_LOOP)
- debugC(2, kDebugLevelSound, " => Loop: %d (0x%x)", *cue, *cue);
- else
- debugC(2, kDebugLevelSound, " => Cue: %d (0x%x)", *cue, *cue);
-
- }
- return result;
-
- default:
- if (result > 0)
- song->_wakeupTime = song->_wakeupTime.addFrames(result);
-
- /* Delay */
- break;
- }
- }
-
-}
-
-
-/*****************/
-/* Song basics */
-/*****************/
-
-void SfxState::sfx_add_song(SongIterator *it, int priority, SongHandle handle, int number) {
- Song *song = _songlib.findSong(handle);
-
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Adding song: %08lx at %d, it=%p\n", handle, priority, it);
-#endif
- if (!it) {
- error("[SFX] Attempt to add empty song with handle %08lx", handle);
- return;
- }
-
- it->init();
-
- /* If we're already playing this, stop it */
- /* Tell player to shut up */
-// _dump_songs(this);
-
- if (_player)
- _player->iterator_message(SongIterator::Message(handle, SIMSG_STOP));
-
- if (song) {
- setSongStatus( song, SOUND_STATUS_STOPPED);
-
- fprintf(stderr, "Overwriting old song (%08lx) ...\n", handle);
- if (song->_status == SOUND_STATUS_PLAYING || song->_status == SOUND_STATUS_SUSPENDED) {
- delete it;
- error("Unexpected (error): Song %ld still playing/suspended (%d)",
- handle, song->_status);
- return;
- } else {
- _songlib.removeSong(handle); /* No duplicates */
- }
-
- }
-
- song = new Song(handle, it, priority);
- song->_resourceNum = number;
- song->_hold = 0;
- song->_loops = 0;
- song->_wakeupTime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC);
- _songlib.addSong(song);
- _song = NULL; /* As above */
- update();
-
- return;
-}
-
-void SfxState::sfx_remove_song(SongHandle handle) {
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Removing song: %08lx\n", handle);
-#endif
- if (_song && _song->_handle == handle)
- _song = NULL;
-
- _songlib.removeSong(handle);
- update();
-}
-
-
-
-/**********************/
-/* Song modifications */
-/**********************/
-
-#define ASSERT_SONG(s) if (!(s)) { warning("Looking up song handle %08lx failed in %s, L%d", handle, __FILE__, __LINE__); return; }
-
-void SfxState::sfx_song_set_status(SongHandle handle, int status) {
- Song *song = _songlib.findSong(handle);
- ASSERT_SONG(song);
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Setting song status to %d"
- " (0:stop, 1:play, 2:susp, 3:wait): %08lx\n", status, handle);
-#endif
-
- setSongStatus(song, status);
-
- update();
-}
-
-void SfxState::sfx_song_set_fade(SongHandle handle, fade_params_t *params) {
-#ifdef DEBUG_SONG_API
- static const char *stopmsg[] = {"??? Should not happen", "Do not stop afterwards", "Stop afterwards"};
-#endif
- Song *song = _songlib.findSong(handle);
-
- ASSERT_SONG(song);
-
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Setting fade params of %08lx to "
- "final volume %d in steps of %d per %d ticks. %s.",
- handle, fade->final_volume, fade->step_size, fade->ticks_per_step,
- stopmsg[fade->action]);
-#endif
-
- SIMSG_SEND_FADE(song->_it, params);
-
- update();
-}
-
-void SfxState::sfx_song_renice(SongHandle handle, int priority) {
- Song *song = _songlib.findSong(handle);
- ASSERT_SONG(song);
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Renicing song %08lx to %d\n",
- handle, priority);
-#endif
-
- song->_priority = priority;
-
- update();
-}
-
-void SfxState::sfx_song_set_loops(SongHandle handle, int loops) {
- Song *song = _songlib.findSong(handle);
- SongIterator::Message msg = SongIterator::Message(handle, SIMSG_SET_LOOPS(loops));
- ASSERT_SONG(song);
-
- song->_loops = loops;
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Setting loops on %08lx to %d\n",
- handle, loops);
-#endif
- songit_handle_message(&(song->_it), msg);
-
- if (_player/* && _player->send_iterator_message*/)
- /* FIXME: The above should be optional! */
- _player->iterator_message(msg);
-}
-
-void SfxState::sfx_song_set_hold(SongHandle handle, int hold) {
- Song *song = _songlib.findSong(handle);
- SongIterator::Message msg = SongIterator::Message(handle, SIMSG_SET_HOLD(hold));
- ASSERT_SONG(song);
-
- song->_hold = hold;
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] Setting hold on %08lx to %d\n",
- handle, hold);
-#endif
- songit_handle_message(&(song->_it), msg);
-
- if (_player/* && _player->send_iterator_message*/)
- /* FIXME: The above should be optional! */
- _player->iterator_message(msg);
-}
-
-/* Different from the one in iterator.c */
-static const int MIDI_cmdlen[16] = {0, 0, 0, 0, 0, 0, 0, 0,
- 3, 3, 0, 3, 2, 0, 3, 0
- };
-
-static const SongHandle midi_send_base = 0xffff0000;
-
-Common::Error SfxState::sfx_send_midi(SongHandle handle, int channel,
- int command, int arg1, int arg2) {
- byte buffer[5];
-
- /* Yes, in that order. SCI channel mutes are actually done via
- a counting semaphore. 0 means to decrement the counter, 1
- to increment it. */
- static const char *channel_state[] = {"ON", "OFF"};
-
- if (command == 0xb0 &&
- arg1 == SCI_MIDI_CHANNEL_MUTE) {
- warning("TODO: channel mute (channel %d %s)", channel, channel_state[arg2]);
- /* We need to have a GET_PLAYMASK interface to use
- here. SET_PLAYMASK we've got.
- */
- return Common::kNoError;
- }
-
- buffer[0] = channel | command; /* No channel remapping yet */
-
- switch (command) {
- case 0x80 :
- case 0x90 :
- case 0xb0 :
- buffer[1] = arg1 & 0xff;
- buffer[2] = arg2 & 0xff;
- break;
- case 0xc0 :
- buffer[1] = arg1 & 0xff;
- break;
- case 0xe0 :
- buffer[1] = (arg1 & 0x7f) | 0x80;
- buffer[2] = (arg1 & 0xff00) >> 7;
- break;
- default:
- warning("Unexpected explicit MIDI command %02x", command);
- return Common::kUnknownError;
- }
-
- if (_player)
- _player->tell_synth(MIDI_cmdlen[command >> 4], buffer);
- return Common::kNoError;
-}
-
-int SfxState::sfx_getVolume() {
- return _player->getVolume();
-}
-
-void SfxState::sfx_setVolume(int volume) {
- _player->setVolume(volume);
-}
-
-void SfxState::sfx_all_stop() {
-#ifdef DEBUG_SONG_API
- fprintf(stderr, "[sfx-core] All stop\n");
-#endif
-
- _songlib.freeSounds();
- update();
-}
-
-} // End of namespace Sci
-
-#endif // USE_OLD_MUSIC_FUNCTIONS
diff --git a/engines/sci/sound/iterator/core.h b/engines/sci/sound/iterator/core.h
deleted file mode 100644
index a44fe2ecae..0000000000
--- a/engines/sci/sound/iterator/core.h
+++ /dev/null
@@ -1,209 +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$
- *
- */
-
-/* Sound engine */
-#ifndef SCI_SFX_CORE_H
-#define SCI_SFX_CORE_H
-
-#include "common/error.h"
-
-#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-#include "sci/sound/iterator/songlib.h"
-#include "sci/resource.h"
-
-namespace Sci {
-
-class SfxPlayer;
-class SongIterator;
-struct fade_params_t;
-
-#define SFX_TICKS_PER_SEC 60 /* MIDI ticks per second */
-
-
-#define SFX_STATE_FLAG_MULTIPLAY (1 << 0) /* More than one song playable
-** simultaneously ? */
-#define SFX_STATE_FLAG_NOSOUND (1 << 1) /* Completely disable sound playing */
-
-class SfxState {
-private:
- SfxPlayer *_player;
-
-public: // FIXME, make private
- SongIterator *_it; /**< The song iterator at the heart of things */
- uint _flags; /**< SFX_STATE_FLAG_* */
- SongLibrary _songlib; /**< Song library */
- Song *_song; /**< Active song, or start of active song chain */
- bool _suspended; /**< Whether we are suspended */
- ResourceManager *_resMan;
-
-public:
- SfxState();
- ~SfxState();
-
- /***********/
- /* General */
- /***********/
-
- /* Initializes the sound engine
- ** Parameters: (ResourceManager *) resMan: Resource manager for initialization
- ** (int) flags: SFX_STATE_FLAG_*
- */
- void sfx_init(ResourceManager *resMan, int flags, SciVersion soundVersion);
-
- /** Deinitializes the sound subsystem. */
- void sfx_exit();
-
- /* Suspends/unsuspends the sound sybsystem
- ** Parameters: (int) suspend: Whether to suspend (non-null) or to unsuspend
- */
- void sfx_suspend(bool suspend);
-
- /* Polls the sound server for cues etc.
- ** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise
- ** (SongHandle) *handle: The affected handle
- ** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP)
- */
- int sfx_poll(SongHandle *handle, int *cue);
-
- /* Polls the sound server for cues etc.
- ** Parameters: (SongHandle) handle: The handle to poll
- ** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise
- ** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP)
- */
- int sfx_poll_specific(SongHandle handle, int *cue);
-
- /* Determines the current global volume settings
- ** Returns : (int) The global volume, between 0 (silent) and 127 (max. volume)
- */
- int sfx_getVolume();
-
- /* Determines the current global volume settings
- ** Parameters: (int) volume: The new global volume, between 0 and 127 (see above)
- */
- void sfx_setVolume(int volume);
-
- /* Stops all songs currently playing, purges song library
- */
- void sfx_all_stop();
-
-
- /*****************/
- /* Song basics */
- /*****************/
-
- /* Adds a song to the internal sound library
- ** Parameters: (SongIterator *) it: The iterator describing the song
- ** (int) priority: Initial song priority (higher <-> more important)
- ** (SongHandle) handle: The handle to associate with the song
- */
- void sfx_add_song(SongIterator *it, int priority, SongHandle handle, int resnum);
-
-
- /* Deletes a song and its associated song iterator from the song queue
- ** Parameters: (SongHandle) handle: The song to remove
- */
- void sfx_remove_song(SongHandle handle);
-
-
- /**********************/
- /* Song modifications */
- /**********************/
-
-
- /* Sets the song status, i.e. whether it is playing, suspended, or stopped.
- ** Parameters: (SongHandle) handle: Handle of the song to modify
- ** (int) status: The song status the song should assume
- ** WAITING and PLAYING are set implicitly and essentially describe the same state
- ** as far as this function is concerned.
- */
- void sfx_song_set_status(SongHandle handle, int status);
-
- /* Sets the new song priority
- ** Parameters: (SongHandle) handle: The handle to modify
- ** (int) priority: The priority to set
- */
- void sfx_song_renice(SongHandle handle, int priority);
-
- /* Sets the number of loops for the specified song
- ** Parameters: (SongHandle) handle: The song handle to reference
- ** (int) loops: Number of loops to set
- */
- void sfx_song_set_loops(SongHandle handle, int loops);
-
- /* Sets the number of loops for the specified song
- ** Parameters: (SongHandle) handle: The song handle to reference
- ** (int) hold: Number of loops to setn
- */
- void sfx_song_set_hold(SongHandle handle, int hold);
-
- /* Instructs a song to be faded out
- ** Parameters: (SongHandle) handle: The song handle to reference
- ** (fade_params_t *) fade_setup: The precise fade-out configuration to use
- */
- void sfx_song_set_fade(SongHandle handle, fade_params_t *fade_setup);
-
-
- // Previously undocumented:
- Common::Error sfx_send_midi(SongHandle handle, int channel,
- int command, int arg1, int arg2);
-
- // misc
-
- /**
- * Determines the polyphony of the player in use.
- * @return Number of voices the active player can emit
- */
- int sfx_get_player_polyphony();
-
- /**
- * Tells the player to stop its internal iterator.
- */
- void sfx_reset_player();
-
- /**
- * Pass a raw MIDI event to the synth of the player.
- * @param argc Length of buffer holding the midi event
- * @param argv The buffer itself
- */
- void sfx_player_tell_synth(int buf_nr, byte *buf);
-
-protected:
- void freezeTime();
- void thawTime();
-
- bool isPlaying(Song *song);
- void setSongStatus(Song *song, int status);
- void updateSingleSong();
- void updateMultiSong();
- void update();
-};
-
-} // End of namespace Sci
-
-#endif // USE_OLD_MUSIC_FUNCTIONS
-
-#endif // SCI_SFX_CORE_H
diff --git a/engines/sci/sound/iterator/iterator.cpp b/engines/sci/sound/iterator/iterator.cpp
deleted file mode 100644
index 5d9d63e5af..0000000000
--- a/engines/sci/sound/iterator/iterator.cpp
+++ /dev/null
@@ -1,1686 +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$
- *
- */
-
-/* Song iterators */
-
-#include "common/util.h"
-
-#include "sci/sci.h"
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-
-#include "sci/sound/iterator/iterator_internal.h"
-#include "sci/engine/state.h" // for sfx_player_tell_synth :/
-#include "sci/sound/iterator/core.h" // for sfx_player_tell_synth
-
-#include "sound/audiostream.h"
-#include "sound/mixer.h"
-#include "sound/decoders/raw.h"
-
-namespace Sci {
-
-
-static const int MIDI_cmdlen[16] = {0, 0, 0, 0, 0, 0, 0, 0,
- 2, 2, 2, 2, 1, 1, 2, 0
- };
-
-/*#define DEBUG_DECODING*/
-/*#define DEBUG_VERBOSE*/
-
-/** Find first set bit in bits and return its index. Returns 0 if bits is 0. */
-static int sci_ffs(int bits) {
- if (!bits)
- return 0;
-
- int retval = 1;
-
- while (!(bits & 1)) {
- retval++;
- bits >>= 1;
- }
-
- return retval;
-}
-
-static void print_tabs_id(int nr, songit_id_t id) {
- while (nr-- > 0)
- fprintf(stderr, "\t");
-
- fprintf(stderr, "[%08lx] ", id);
-}
-
-BaseSongIterator::BaseSongIterator(byte *data, uint size, songit_id_t id)
- : _data(data, size) {
- ID = id;
-}
-
-/************************************/
-/*-- SCI0 iterator implementation --*/
-/************************************/
-
-#define SCI0_MIDI_OFFSET 33
-#define SCI0_END_OF_SONG 0xfc /* proprietary MIDI command */
-
-#define SCI0_PCM_SAMPLE_RATE_OFFSET 0x0e
-#define SCI0_PCM_SIZE_OFFSET 0x20
-#define SCI0_PCM_DATA_OFFSET 0x2c
-
-#define CHECK_FOR_END_ABSOLUTE(offset) \
- if (offset > _data.size()) { \
- warning("Reached end of song without terminator (%x/%x) at %d", offset, _data.size(), __LINE__); \
- return SI_FINISHED; \
- }
-
-#define CHECK_FOR_END(offset_augment) \
- if ((channel->offset + (offset_augment)) > channel->end) { \
- channel->state = SI_STATE_FINISHED; \
- warning("Reached end of track %d without terminator (%x+%x/%x) at %d", channel->id, channel->offset, offset_augment, channel->end, __LINE__); \
- return SI_FINISHED; \
- }
-
-
-static int _parse_ticks(byte *data, int *offset_p, int size) {
- int ticks = 0;
- int tempticks;
- int offset = 0;
-
- do {
- tempticks = data[offset++];
- ticks += (tempticks == SCI_MIDI_TIME_EXPANSION_PREFIX) ?
- SCI_MIDI_TIME_EXPANSION_LENGTH : tempticks;
- } while (tempticks == SCI_MIDI_TIME_EXPANSION_PREFIX
- && offset < size);
-
- if (offset_p)
- *offset_p = offset;
-
- return ticks;
-}
-
-
-static int _sci0_get_pcm_data(Sci0SongIterator *self, int *rate, int *xoffset, uint *xsize);
-
-
-#define PARSE_FLAG_LOOPS_UNLIMITED (1 << 0) /* Unlimited # of loops? */
-#define PARSE_FLAG_PARAMETRIC_CUE (1 << 1) /* Assume that cues take an additional "cue value" argument */
-/* This implements a difference between SCI0 and SCI1 cues. */
-
-void SongIteratorChannel::init(int id_, int offset_, int end_) {
- playmask = PLAYMASK_NONE; /* Disable all channels */
- id = id_;
- state = SI_STATE_DELTA_TIME;
- loop_timepos = 0;
- total_timepos = 0;
- timepos_increment = 0;
- delay = 0; /* Only used for more than one channel */
- last_cmd = 0xfe;
-
- offset = loop_offset = initial_offset = offset_;
- end = end_;
-}
-
-void SongIteratorChannel::resetSynthChannels() {
- byte buf[5];
-
- // FIXME: Evil hack
- SfxState &sound = g_sci->getEngineState()->_sound;
-
- for (int i = 0; i < MIDI_CHANNELS; i++) {
- if (playmask & (1 << i)) {
- buf[0] = 0xe0 | i; /* Pitch bend */
- buf[1] = 0x80; /* Wheel center */
- buf[2] = 0x40;
- sound.sfx_player_tell_synth(3, buf);
-
- buf[0] = 0xb0 | i; // Set control
- buf[1] = 0x40; // Hold pedal
- buf[2] = 0x00; // Off
- sound.sfx_player_tell_synth(3, buf);
- /* TODO: Reset other controls? */
- }
- }
-}
-
-int BaseSongIterator::parseMidiCommand(byte *buf, int *result, SongIteratorChannel *channel, int flags) {
- byte cmd;
- int paramsleft;
- int midi_op;
- int midi_channel;
-
- channel->state = SI_STATE_DELTA_TIME;
-
- cmd = _data[channel->offset++];
-
- if (!(cmd & 0x80)) {
- /* 'Running status' mode */
- channel->offset--;
- cmd = channel->last_cmd;
- }
-
- if (cmd == 0xfe) {
- warning("song iterator subsystem: Corrupted sound resource detected.");
- return SI_FINISHED;
- }
-
- midi_op = cmd >> 4;
- midi_channel = cmd & 0xf;
- paramsleft = MIDI_cmdlen[midi_op];
-
-#if 0
- if (1) {
- fprintf(stderr, "[IT]: off=%x, cmd=%02x, takes %d args ",
- channel->offset - 1, cmd, paramsleft);
- fprintf(stderr, "[%02x %02x <%02x> %02x %02x %02x]\n",
- _data[channel->offset-3],
- _data[channel->offset-2],
- _data[channel->offset-1],
- _data[channel->offset],
- _data[channel->offset+1],
- _data[channel->offset+2]);
- }
-#endif
-
- buf[0] = cmd;
-
-
- CHECK_FOR_END(paramsleft);
- memcpy(buf + 1, _data.begin() + channel->offset, paramsleft);
- *result = 1 + paramsleft;
-
- channel->offset += paramsleft;
-
- channel->last_cmd = cmd;
-
- /* Are we supposed to play this channel? */
- if (
- /* First, exclude "global" properties-- such as cues-- from consideration */
- (midi_op < 0xf
- && !(cmd == SCI_MIDI_SET_SIGNAL)
- && !(SCI_MIDI_CONTROLLER(cmd)
- && buf[1] == SCI_MIDI_CUMULATIVE_CUE))
-
- /* Next, check if the channel is allowed */
- && (!((1 << midi_channel) & channel->playmask)))
- return /* Execute next command */
- nextCommand(buf, result);
-
-
- if (cmd == SCI_MIDI_EOT) {
- /* End of track? */
- channel->resetSynthChannels();
- if (_loops > 1) {
- /* If allowed, decrement the number of loops */
- if (!(flags & PARSE_FLAG_LOOPS_UNLIMITED))
- *result = --_loops;
-
-#ifdef DEBUG_DECODING
- fprintf(stderr, "%s L%d: (%p):%d Looping ", __FILE__, __LINE__, this, channel->id);
- if (flags & PARSE_FLAG_LOOPS_UNLIMITED)
- fprintf(stderr, "(indef.)");
- else
- fprintf(stderr, "(%d)", _loops);
- fprintf(stderr, " %x -> %x\n",
- channel->offset, channel->loop_offset);
-#endif
- channel->offset = channel->loop_offset;
- channel->state = SI_STATE_DELTA_TIME;
- channel->total_timepos = channel->loop_timepos;
- channel->last_cmd = 0xfe;
- debugC(2, kDebugLevelSound, "Looping song iterator %08lx.", ID);
- return SI_LOOP;
- } else {
- channel->state = SI_STATE_FINISHED;
- return SI_FINISHED;
- }
-
- } else if (cmd == SCI_MIDI_SET_SIGNAL) {
- if (buf[1] == SCI_MIDI_SET_SIGNAL_LOOP) {
- channel->loop_offset = channel->offset;
- channel->loop_timepos = channel->total_timepos;
-
- return /* Execute next command */
- nextCommand(buf, result);
- } else {
- /* Used to be conditional <= 127 */
- *result = buf[1]; /* Absolute cue */
- return SI_ABSOLUTE_CUE;
- }
- } else if (SCI_MIDI_CONTROLLER(cmd)) {
- switch (buf[1]) {
-
- case SCI_MIDI_CUMULATIVE_CUE:
- if (flags & PARSE_FLAG_PARAMETRIC_CUE)
- _ccc += buf[2];
- else { /* No parameter to CC */
- _ccc++;
- /* channel->offset--; */
- }
- *result = _ccc;
- return SI_RELATIVE_CUE;
-
- case SCI_MIDI_RESET_ON_SUSPEND:
- _resetflag = buf[2];
- break;
-
- case SCI_MIDI_SET_POLYPHONY:
- _polyphony[midi_channel] = buf[2];
-
-#if 0
- {
- Sci1SongIterator *self1 = (Sci1SongIterator *)this;
- int i;
- int voices = 0;
- for (i = 0; i < self1->_numChannels; i++) {
- voices += _polyphony[i];
- }
-
- printf("SET_POLYPHONY(%d, %d) for a total of %d voices\n", midi_channel, buf[2], voices);
- printf("[iterator] DEBUG: Polyphony = [ ");
- for (i = 0; i < self1->_numChannels; i++)
- printf("%d ", _polyphony[i]);
- printf("]\n");
- printf("[iterator] DEBUG: Importance = [ ");
- printf("]\n");
- }
-#endif
- break;
-
- case SCI_MIDI_SET_REVERB:
- break;
-
- case SCI_MIDI_CHANNEL_MUTE:
- warning("CHANNEL_MUTE(%d, %d)", midi_channel, buf[2]);
- break;
-
- case SCI_MIDI_HOLD: {
- // Safe cast: This controller is only used in SCI1
- Sci1SongIterator *self1 = (Sci1SongIterator *)this;
-
- if (buf[2] == self1->_hold) {
- channel->offset = channel->initial_offset;
- channel->state = SI_STATE_COMMAND;
- channel->total_timepos = 0;
-
- self1->_numLoopedChannels = self1->_numActiveChannels - 1;
-
- // FIXME:
- // This implementation of hold breaks getting out of the
- // limo when visiting the airport near the start of LSL5.
- // It seems like all channels should be reset here somehow,
- // but not sure how.
- // Forcing all channel offsets to 0 seems to fix the hang,
- // but somehow slows the exit sequence down to take 20 seconds
- // instead of about 3.
-
- return SI_LOOP;
- }
-
- break;
- }
- case 0x04: /* UNKNOWN NYI (happens in LSL2 gameshow) */
- case 0x46: /* UNKNOWN NYI (happens in LSL3 binoculars) */
- case 0x61: /* UNKNOWN NYI (special for AdLib? Iceman) */
- case 0x73: /* UNKNOWN NYI (happens in Hoyle) */
- case 0xd1: /* UNKNOWN NYI (happens in KQ4 when riding the unicorn) */
- return /* Execute next command */
- nextCommand(buf, result);
-
- case 0x01: /* modulation */
- case 0x07: /* volume */
- case 0x0a: /* panpot */
- case 0x0b: /* expression */
- case 0x40: /* hold */
- case 0x79: /* reset all */
- /* No special treatment neccessary */
- break;
-
- }
- return 0;
-
- } else {
-#if 0
- /* Perform remapping, if neccessary */
- if (cmd != SCI_MIDI_SET_SIGNAL
- && cmd < 0xf0) { /* Not a generic command */
- int chan = cmd & 0xf;
- int op = cmd & 0xf0;
-
- chan = channel_remap[chan];
- buf[0] = chan | op;
- }
-#endif
-
- /* Process as normal MIDI operation */
- return 0;
- }
-}
-
-int BaseSongIterator::processMidi(byte *buf, int *result,
- SongIteratorChannel *channel, int flags) {
- CHECK_FOR_END(0);
-
- switch (channel->state) {
-
- case SI_STATE_PCM: {
- if (_data[channel->offset] == 0
- && _data[channel->offset + 1] == SCI_MIDI_EOT)
- /* Fake one extra tick to trick the interpreter into not killing the song iterator right away */
- channel->state = SI_STATE_PCM_MAGIC_DELTA;
- else
- channel->state = SI_STATE_DELTA_TIME;
- return SI_PCM;
- }
-
- case SI_STATE_PCM_MAGIC_DELTA: {
- int rate;
- int offset;
- uint size;
- int delay;
- if (_sci0_get_pcm_data((Sci0SongIterator *)this, &rate, &offset, &size))
- return SI_FINISHED; /* 'tis broken */
- channel->state = SI_STATE_FINISHED;
- delay = (size * 50 + rate - 1) / rate; /* number of ticks to completion*/
-
- debugC(2, kDebugLevelSound, "delaying %d ticks", delay);
- return delay;
- }
-
- case SI_STATE_UNINITIALISED:
- warning("Attempt to read command from uninitialized iterator");
- init();
- return nextCommand(buf, result);
-
- case SI_STATE_FINISHED:
- return SI_FINISHED;
-
- case SI_STATE_DELTA_TIME: {
- int offset;
- int ticks = _parse_ticks(_data.begin() + channel->offset,
- &offset,
- _data.size() - channel->offset);
-
- channel->offset += offset;
- channel->delay += ticks;
- channel->timepos_increment = ticks;
-
- CHECK_FOR_END(0);
-
- channel->state = SI_STATE_COMMAND;
-
- if (ticks)
- return ticks;
- }
-
- /* continute otherwise... */
-
- case SI_STATE_COMMAND: {
- int retval;
- channel->total_timepos += channel->timepos_increment;
- channel->timepos_increment = 0;
-
- retval = parseMidiCommand(buf, result, channel, flags);
-
- if (retval == SI_FINISHED) {
- if (_numActiveChannels)
- --(_numActiveChannels);
-#ifdef DEBUG_DECODING
- fprintf(stderr, "%s L%d: (%p):%d Finished channel, %d channels left\n",
- __FILE__, __LINE__, this, channel->id,
- _numActiveChannels);
-#endif
- /* If we still have channels left... */
- if (_numActiveChannels) {
- return nextCommand(buf, result);
- }
-
- /* Otherwise, we have reached the end */
- _loops = 0;
- }
-
- return retval;
- }
-
- default:
- error("Invalid iterator state %d", channel->state);
- return SI_FINISHED;
- }
-}
-
-int Sci0SongIterator::nextCommand(byte *buf, int *result) {
- return processMidi(buf, result, &_channel, PARSE_FLAG_PARAMETRIC_CUE);
-}
-
-static int _sci0_header_magic_p(byte *data, int offset, int size) {
- if (offset + 0x10 > size)
- return 0;
- return (data[offset] == 0x1a)
- && (data[offset + 1] == 0x00)
- && (data[offset + 2] == 0x01)
- && (data[offset + 3] == 0x00);
-}
-
-
-static int _sci0_get_pcm_data(Sci0SongIterator *self,
- int *rate, int *xoffset, uint *xsize) {
- int tries = 2;
- bool found_it = false;
- byte *pcm_data;
- int size;
- uint offset = SCI0_MIDI_OFFSET;
-
- if (self->_data[0] != 2)
- return 1;
- /* No such luck */
-
- while ((tries--) && (offset < self->_data.size()) && (!found_it)) {
- // Search through the garbage manually
- // FIXME: Replace offset by an iterator
- Common::Array<byte>::iterator iter = Common::find(self->_data.begin() + offset, self->_data.end(), SCI0_END_OF_SONG);
-
- if (iter == self->_data.end()) {
- warning("Playing unterminated song");
- return 1;
- }
-
- // add one to move it past the END_OF_SONG marker
- iter++;
- offset = iter - self->_data.begin(); // FIXME
-
-
- if (_sci0_header_magic_p(self->_data.begin(), offset, self->_data.size()))
- found_it = true;
- }
-
- if (!found_it) {
- warning("Song indicates presence of PCM, but"
- " none found (finally at offset %04x)", offset);
-
- return 1;
- }
-
- pcm_data = self->_data.begin() + offset;
-
- size = READ_LE_UINT16(pcm_data + SCI0_PCM_SIZE_OFFSET);
-
- /* Two of the format parameters are fixed by design: */
- *rate = READ_LE_UINT16(pcm_data + SCI0_PCM_SAMPLE_RATE_OFFSET);
-
- if (offset + SCI0_PCM_DATA_OFFSET + size != self->_data.size()) {
- int d = offset + SCI0_PCM_DATA_OFFSET + size - self->_data.size();
-
- warning("PCM advertizes %d bytes of data, but %d"
- " bytes are trailing in the resource",
- size, self->_data.size() - (offset + SCI0_PCM_DATA_OFFSET));
-
- if (d > 0)
- size -= d; /* Fix this */
- }
-
- *xoffset = offset;
- *xsize = size;
-
- return 0;
-}
-
-static Audio::AudioStream *makeStream(byte *data, int size, int rate) {
- debugC(2, kDebugLevelSound, "Playing PCM data of size %d, rate %d", size, rate);
-
- // Duplicate the data
- byte *sound = (byte *)malloc(size);
- memcpy(sound, data, size);
-
- // Convert stream format flags
- int flags = Audio::FLAG_UNSIGNED;
- return Audio::makeRawStream(sound, size, rate, flags);
-}
-
-Audio::AudioStream *Sci0SongIterator::getAudioStream() {
- int rate;
- int offset;
- uint size;
- if (_sci0_get_pcm_data(this, &rate, &offset, &size))
- return NULL;
-
- _channel.state = SI_STATE_FINISHED; /* Don't play both PCM and music */
-
- return makeStream(_data.begin() + offset + SCI0_PCM_DATA_OFFSET, size, rate);
-}
-
-SongIterator *Sci0SongIterator::handleMessage(Message msg) {
- if (msg._class == _SIMSG_BASE) {
- switch (msg._type) {
-
- case _SIMSG_BASEMSG_PRINT:
- print_tabs_id(msg._arg.i, ID);
- debugC(2, kDebugLevelSound, "SCI0: dev=%d, active-chan=%d, size=%d, loops=%d",
- _deviceId, _numActiveChannels, _data.size(), _loops);
- break;
-
- case _SIMSG_BASEMSG_SET_LOOPS:
- _loops = msg._arg.i;
- break;
-
- case _SIMSG_BASEMSG_STOP: {
- songit_id_t sought_id = msg.ID;
-
- if (sought_id == ID)
- _channel.state = SI_STATE_FINISHED;
- break;
- }
-
- case _SIMSG_BASEMSG_SET_PLAYMASK: {
- int i;
- _deviceId = msg._arg.i;
-
- /* Set all but the rhytm channel mask bits */
- _channel.playmask &= ~(1 << MIDI_RHYTHM_CHANNEL);
-
- for (i = 0; i < MIDI_CHANNELS; i++)
- if (_data[2 + (i << 1)] & _deviceId
- && i != MIDI_RHYTHM_CHANNEL)
- _channel.playmask |= (1 << i);
- }
- break;
-
- case _SIMSG_BASEMSG_SET_RHYTHM:
- _channel.playmask &= ~(1 << MIDI_RHYTHM_CHANNEL);
- if (msg._arg.i)
- _channel.playmask |= (1 << MIDI_RHYTHM_CHANNEL);
- break;
-
- case _SIMSG_BASEMSG_SET_FADE: {
- fade_params_t *fp = (fade_params_t *) msg._arg.p;
- fade.action = fp->action;
- fade.final_volume = fp->final_volume;
- fade.ticks_per_step = fp->ticks_per_step;
- fade.step_size = fp->step_size;
- break;
- }
-
- default:
- return NULL;
- }
-
- return this;
- }
- return NULL;
-}
-
-int Sci0SongIterator::getTimepos() {
- return _channel.total_timepos;
-}
-
-Sci0SongIterator::Sci0SongIterator(byte *data, uint size, songit_id_t id)
- : BaseSongIterator(data, size, id) {
- channel_mask = 0xffff; // Allocate all channels by default
- _channel.state = SI_STATE_UNINITIALISED;
-
- for (int i = 0; i < MIDI_CHANNELS; i++)
- _polyphony[i] = data[1 + (i << 1)];
-
- init();
-}
-
-void Sci0SongIterator::init() {
- fade.action = FADE_ACTION_NONE;
- _resetflag = 0;
- _loops = 0;
- priority = 0;
-
- _ccc = 0; /* Reset cumulative cue counter */
- _numActiveChannels = 1;
- _channel.init(0, SCI0_MIDI_OFFSET, _data.size());
- _channel.resetSynthChannels();
-
- if (_data[0] == 2) /* Do we have an embedded PCM? */
- _channel.state = SI_STATE_PCM;
-}
-
-SongIterator *Sci0SongIterator::clone(int delta) {
- Sci0SongIterator *newit = new Sci0SongIterator(*this);
- return newit;
-}
-
-
-/***************************/
-/*-- SCI1 song iterators --*/
-/***************************/
-
-int Sci1SongIterator::initSample(const int offset) {
- Sci1Sample sample;
- int rate;
- int length;
- int begin;
- int end;
-
- CHECK_FOR_END_ABSOLUTE((uint)offset + 10);
- if (_data[offset + 1] != 0)
- warning("[iterator-1] In sample at offset 0x04x: Byte #1 is %02x instead of zero",
- _data[offset + 1]);
-
- rate = (int16)READ_LE_UINT16(_data.begin() + offset + 2);
- length = READ_LE_UINT16(_data.begin() + offset + 4);
- begin = (int16)READ_LE_UINT16(_data.begin() + offset + 6);
- end = (int16)READ_LE_UINT16(_data.begin() + offset + 8);
-
- CHECK_FOR_END_ABSOLUTE((uint)(offset + 10 + length));
-
- sample.delta = begin;
- sample.size = length;
- sample._data = _data.begin() + offset + 10;
-
-#ifdef DEBUG_VERBOSE
- fprintf(stderr, "[SAMPLE] %x/%x/%x/%x l=%x\n",
- offset + 10, begin, end, _data.size(), length);
-#endif
-
- sample.rate = rate;
-
- sample.announced = false;
-
- /* Insert into the sample list at the right spot, keeping it sorted by delta */
- Common::List<Sci1Sample>::iterator seeker = _samples.begin();
- while (seeker != _samples.end() && seeker->delta < begin)
- ++seeker;
- _samples.insert(seeker, sample);
-
- return 0; /* Everything's fine */
-}
-
-int Sci1SongIterator::initSong() {
- int last_time;
- uint offset = 0;
- _numChannels = 0;
- _samples.clear();
-// _deviceId = 0x0c;
-
- if (_data[offset] == 0xf0) {
- priority = _data[offset + 1];
-
- offset += 8;
- }
-
- while (_data[offset] != 0xff
- && _data[offset] != _deviceId) {
- offset++;
- CHECK_FOR_END_ABSOLUTE(offset + 1);
- while (_data[offset] != 0xff) {
- CHECK_FOR_END_ABSOLUTE(offset + 7);
- offset += 6;
- }
- offset++;
- }
-
- if (_data[offset] == 0xff) {
- warning("[iterator] Song does not support hardware 0x%02x", _deviceId);
- return 1;
- }
-
- offset++;
-
- while (_data[offset] != 0xff) { /* End of list? */
- uint track_offset;
- int end;
- offset += 2;
-
- CHECK_FOR_END_ABSOLUTE(offset + 4);
-
- track_offset = READ_LE_UINT16(_data.begin() + offset);
- end = READ_LE_UINT16(_data.begin() + offset + 2);
-
- CHECK_FOR_END_ABSOLUTE(track_offset - 1);
-
- if (_data[track_offset] == 0xfe) {
- if (initSample(track_offset))
- return 1; /* Error */
- } else {
- /* Regular MIDI channel */
- if (_numChannels >= MIDI_CHANNELS) {
- warning("[iterator] Song has more than %d channels, cutting them off",
- MIDI_CHANNELS);
- break; /* Scan for remaining samples */
- } else {
- int channel_nr = _data[track_offset] & 0xf;
- SongIteratorChannel &channel = _channels[_numChannels++];
-
- /*
- if (_data[track_offset] & 0xf0)
- printf("Channel %d has mapping bits %02x\n",
- channel_nr, _data[track_offset] & 0xf0);
- */
-
- // Add 2 to skip over header bytes */
- channel.init(channel_nr, track_offset + 2, track_offset + end);
- channel.resetSynthChannels();
-
- _polyphony[_numChannels - 1] = _data[channel.offset - 1] & 15;
-
- channel.playmask = ~0; /* Enable all */
- channel_mask |= (1 << channel_nr);
-
- CHECK_FOR_END_ABSOLUTE(offset + end);
- }
- }
- offset += 4;
- CHECK_FOR_END_ABSOLUTE(offset);
- }
-
- /* Now ensure that sample deltas are relative to the previous sample */
- last_time = 0;
- _numActiveChannels = _numChannels;
- _numLoopedChannels = 0;
-
- for (Common::List<Sci1Sample>::iterator seeker = _samples.begin();
- seeker != _samples.end(); ++seeker) {
- int prev_last_time = last_time;
- //printf("[iterator] Detected sample: %d Hz, %d bytes at time %d\n",
- // seeker->format.rate, seeker->size, seeker->delta);
- last_time = seeker->delta;
- seeker->delta -= prev_last_time;
- }
-
- return 0; /* Success */
-}
-
-int Sci1SongIterator::getSmallestDelta() const {
- int d = -1;
- for (int i = 0; i < _numChannels; i++)
- if (_channels[i].state == SI_STATE_COMMAND
- && (d == -1 || _channels[i].delay < d))
- d = _channels[i].delay;
-
- if (!_samples.empty() && _samples.begin()->delta < d)
- return _samples.begin()->delta;
- else
- return d;
-}
-
-void Sci1SongIterator::updateDelta(int delta) {
- if (!_samples.empty())
- _samples.begin()->delta -= delta;
-
- for (int i = 0; i < _numChannels; i++)
- if (_channels[i].state == SI_STATE_COMMAND)
- _channels[i].delay -= delta;
-}
-
-bool Sci1SongIterator::noDeltaTime() const {
- for (int i = 0; i < _numChannels; i++)
- if (_channels[i].state == SI_STATE_DELTA_TIME)
- return false;
- return true;
-}
-
-#define COMMAND_INDEX_NONE -1
-#define COMMAND_INDEX_PCM -2
-
-int Sci1SongIterator::getCommandIndex() const {
- /* Determine the channel # of the next active event, or -1 */
- int i;
- int base_delay = 0x7ffffff;
- int best_chan = COMMAND_INDEX_NONE;
-
- for (i = 0; i < _numChannels; i++)
- if ((_channels[i].state != SI_STATE_PENDING)
- && (_channels[i].state != SI_STATE_FINISHED)) {
-
- if ((_channels[i].state == SI_STATE_DELTA_TIME)
- && (_channels[i].delay == 0))
- return i;
- /* First, read all unknown delta times */
-
- if (_channels[i].delay < base_delay) {
- best_chan = i;
- base_delay = _channels[i].delay;
- }
- }
-
- if (!_samples.empty() && base_delay >= _samples.begin()->delta)
- return COMMAND_INDEX_PCM;
-
- return best_chan;
-}
-
-
-Audio::AudioStream *Sci1SongIterator::getAudioStream() {
- Common::List<Sci1Sample>::iterator sample = _samples.begin();
- if (sample != _samples.end() && sample->delta <= 0) {
- Audio::AudioStream *feed = makeStream(sample->_data, sample->size, sample->rate);
- _samples.erase(sample);
-
- return feed;
- } else
- return NULL;
-}
-
-int Sci1SongIterator::nextCommand(byte *buf, int *result) {
-
- if (!_initialised) {
- //printf("[iterator] DEBUG: Initialising for %d\n", _deviceId);
- _initialised = true;
- if (initSong())
- return SI_FINISHED;
- }
-
-
- if (_delayRemaining) {
- int delay = _delayRemaining;
- _delayRemaining = 0;
- return delay;
- }
-
- int retval = 0;
- do { /* All delays must be processed separately */
- int chan = getCommandIndex();
-
- if (chan == COMMAND_INDEX_NONE) {
- return SI_FINISHED;
- }
-
- if (chan == COMMAND_INDEX_PCM) {
-
- if (_samples.begin()->announced) {
- /* Already announced; let's discard it */
- Audio::AudioStream *feed = getAudioStream();
- delete feed;
- } else {
- int delay = _samples.begin()->delta;
-
- if (delay) {
- updateDelta(delay);
- return delay;
- }
- /* otherwise we're touching a PCM */
- _samples.begin()->announced = true;
- return SI_PCM;
- }
- } else { /* Not a PCM */
-
- retval = processMidi(buf, result,
- &(_channels[chan]),
- PARSE_FLAG_LOOPS_UNLIMITED);
-
- if (retval == SI_LOOP) {
- _numLoopedChannels++;
- _channels[chan].state = SI_STATE_PENDING;
- _channels[chan].delay = 0;
-
- if (_numLoopedChannels == _numActiveChannels) {
- int i;
-
- /* Everyone's ready: Let's loop */
- for (i = 0; i < _numChannels; i++)
- if (_channels[i].state == SI_STATE_PENDING)
- _channels[i].state = SI_STATE_DELTA_TIME;
-
- _numLoopedChannels = 0;
- return SI_LOOP;
- }
- } else if (retval == SI_FINISHED) {
-#ifdef DEBUG
- fprintf(stderr, "FINISHED some channel\n");
-#endif
- } else if (retval > 0) {
- int sd ;
- sd = getSmallestDelta();
-
- if (noDeltaTime() && sd) {
- /* No other channel is ready */
- updateDelta(sd);
-
- /* Only from here do we return delta times */
- return sd;
- }
- }
-
- } /* Not a PCM */
-
- } while (retval > 0);
-
- return retval;
-}
-
-SongIterator *Sci1SongIterator::handleMessage(Message msg) {
- if (msg._class == _SIMSG_BASE) { /* May extend this in the future */
- switch (msg._type) {
-
- case _SIMSG_BASEMSG_PRINT: {
- int playmask = 0;
- int i;
-
- for (i = 0; i < _numChannels; i++)
- playmask |= _channels[i].playmask;
-
- print_tabs_id(msg._arg.i, ID);
- debugC(2, kDebugLevelSound, "SCI1: chan-nr=%d, playmask=%04x",
- _numChannels, playmask);
- }
- break;
-
- case _SIMSG_BASEMSG_STOP: {
- songit_id_t sought_id = msg.ID;
- int i;
-
- if (sought_id == ID) {
- ID = 0;
-
- for (i = 0; i < _numChannels; i++)
- _channels[i].state = SI_STATE_FINISHED;
- }
- break;
- }
-
- case _SIMSG_BASEMSG_SET_PLAYMASK:
- if (msg.ID == ID) {
- channel_mask = 0;
-
- _deviceId = msg._arg.i;
-
- if (_initialised) {
- int i;
- int toffset = -1;
-
- for (i = 0; i < _numChannels; i++)
- if (_channels[i].state != SI_STATE_FINISHED
- && _channels[i].total_timepos > toffset) {
- toffset = _channels[i].total_timepos
- + _channels[i].timepos_increment
- - _channels[i].delay;
- }
-
- /* Find an active channel so that we can
- ** get the correct time offset */
-
- initSong();
-
- toffset -= _delayRemaining;
- _delayRemaining = 0;
-
- if (toffset > 0)
- return new_fast_forward_iterator(this, toffset);
- } else {
- initSong();
- _initialised = true;
- }
-
- break;
-
- }
-
- case _SIMSG_BASEMSG_SET_LOOPS:
- if (msg.ID == ID)
- _loops = (msg._arg.i > 32767) ? 99 : 0;
- /* 99 is arbitrary, but we can't use '1' because of
- ** the way we're testing in the decoding section. */
- break;
-
- case _SIMSG_BASEMSG_SET_HOLD:
- _hold = msg._arg.i;
- break;
- case _SIMSG_BASEMSG_SET_RHYTHM:
- /* Ignore */
- break;
-
- case _SIMSG_BASEMSG_SET_FADE: {
- fade_params_t *fp = (fade_params_t *) msg._arg.p;
- fade.action = fp->action;
- fade.final_volume = fp->final_volume;
- fade.ticks_per_step = fp->ticks_per_step;
- fade.step_size = fp->step_size;
- break;
- }
-
- default:
- warning("Unsupported command %d to SCI1 iterator", msg._type);
- }
- return this;
- }
- return NULL;
-}
-
-Sci1SongIterator::Sci1SongIterator(byte *data, uint size, songit_id_t id)
- : BaseSongIterator(data, size, id) {
- channel_mask = 0; // Defer channel allocation
-
- for (int i = 0; i < MIDI_CHANNELS; i++)
- _polyphony[i] = 0; // Unknown
-
- init();
-}
-
-void Sci1SongIterator::init() {
- fade.action = FADE_ACTION_NONE;
- _resetflag = 0;
- _loops = 0;
- priority = 0;
-
- _ccc = 0;
- _deviceId = 0x00; // Default to Sound Blaster/AdLib for purposes of cue computation
- _numChannels = 0;
- _initialised = false;
- _delayRemaining = 0;
- _loops = 0;
- _hold = 0;
- memset(_polyphony, 0, sizeof(_polyphony));
-}
-
-Sci1SongIterator::~Sci1SongIterator() {
-}
-
-
-SongIterator *Sci1SongIterator::clone(int delta) {
- Sci1SongIterator *newit = new Sci1SongIterator(*this);
- newit->_delayRemaining = delta;
- return newit;
-}
-
-int Sci1SongIterator::getTimepos() {
- int max = 0;
- int i;
-
- for (i = 0; i < _numChannels; i++)
- if (_channels[i].total_timepos > max)
- max = _channels[i].total_timepos;
-
- return max;
-}
-
-/**
- * A song iterator with the purpose of sending notes-off channel commands.
- */
-class CleanupSongIterator : public SongIterator {
-public:
- CleanupSongIterator(uint channels) {
- channel_mask = channels;
- ID = 17;
- }
-
- int nextCommand(byte *buf, int *result);
- Audio::AudioStream *getAudioStream() { return NULL; }
- SongIterator *handleMessage(Message msg);
- int getTimepos() { return 0; }
- SongIterator *clone(int delta) { return new CleanupSongIterator(*this); }
-};
-
-SongIterator *CleanupSongIterator::handleMessage(Message msg) {
- if (msg._class == _SIMSG_BASEMSG_PRINT && msg._type == _SIMSG_BASEMSG_PRINT) {
- print_tabs_id(msg._arg.i, ID);
- debugC(2, kDebugLevelSound, "CLEANUP");
- }
-
- return NULL;
-}
-
-int CleanupSongIterator::nextCommand(byte *buf, int *result) {
- /* Task: Return channel-notes-off for each channel */
- if (channel_mask) {
- int bs = sci_ffs(channel_mask) - 1;
-
- channel_mask &= ~(1 << bs);
- buf[0] = 0xb0 | bs; /* Controller */
- buf[1] = SCI_MIDI_CHANNEL_NOTES_OFF;
- buf[2] = 0; /* Hmm... */
- *result = 3;
- return 0;
- } else
- return SI_FINISHED;
-}
-
-/**********************/
-/*-- Timer iterator --*/
-/**********************/
-int TimerSongIterator::nextCommand(byte *buf, int *result) {
- if (_delta) {
- int d = _delta;
- _delta = 0;
- return d;
- }
- return SI_FINISHED;
-}
-
-SongIterator *new_timer_iterator(int delta) {
- return new TimerSongIterator(delta);
-}
-
-/**********************************/
-/*-- Fast-forward song iterator --*/
-/**********************************/
-
-int FastForwardSongIterator::nextCommand(byte *buf, int *result) {
- if (_delta <= 0)
- return SI_MORPH; /* Did our duty */
-
- while (1) {
- int rv = _delegate->nextCommand(buf, result);
-
- if (rv > 0) {
- /* Subtract from the delta we want to wait */
- _delta -= rv;
-
- /* Done */
- if (_delta < 0)
- return -_delta;
- }
-
- if (rv <= 0)
- return rv;
- }
-}
-
-Audio::AudioStream *FastForwardSongIterator::getAudioStream() {
- return _delegate->getAudioStream();
-}
-
-SongIterator *FastForwardSongIterator::handleMessage(Message msg) {
- if (msg._class == _SIMSG_PLASTICWRAP) {
- assert(msg._type == _SIMSG_PLASTICWRAP_ACK_MORPH);
-
- if (_delta <= 0) {
- SongIterator *it = _delegate;
- delete this;
- return it;
- }
-
- warning("[ff-iterator] Morphing without need");
- return this;
- }
-
- if (msg._class == _SIMSG_BASE && msg._type == _SIMSG_BASEMSG_PRINT) {
- print_tabs_id(msg._arg.i, ID);
- debugC(2, kDebugLevelSound, "FASTFORWARD:");
- msg._arg.i++;
- }
-
- // And continue with the delegate
- songit_handle_message(&_delegate, msg);
-
- return NULL;
-}
-
-
-int FastForwardSongIterator::getTimepos() {
- return _delegate->getTimepos();
-}
-
-FastForwardSongIterator::FastForwardSongIterator(SongIterator *capsit, int delta)
- : _delegate(capsit), _delta(delta) {
-
- channel_mask = capsit->channel_mask;
-}
-
-SongIterator *FastForwardSongIterator::clone(int delta) {
- FastForwardSongIterator *newit = new FastForwardSongIterator(*this);
- newit->_delegate = _delegate->clone(delta);
- return newit;
-}
-
-SongIterator *new_fast_forward_iterator(SongIterator *capsit, int delta) {
- if (capsit == NULL)
- return NULL;
-
- FastForwardSongIterator *it = new FastForwardSongIterator(capsit, delta);
- return it;
-}
-
-
-/********************/
-/*-- Tee iterator --*/
-/********************/
-
-
-static void song_iterator_add_death_listener(SongIterator *it, TeeSongIterator *client) {
- for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) {
- if (it->_deathListeners[i] == 0) {
- it->_deathListeners[i] = client;
- return;
- }
- }
- error("FATAL: Too many death listeners for song iterator");
-}
-
-static void song_iterator_remove_death_listener(SongIterator *it, TeeSongIterator *client) {
- for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) {
- if (it->_deathListeners[i] == client) {
- it->_deathListeners[i] = 0;
- return;
- }
- }
-}
-
-static void song_iterator_transfer_death_listeners(SongIterator *it, SongIterator *it_from) {
- for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) {
- if (it_from->_deathListeners[i])
- song_iterator_add_death_listener(it, it_from->_deathListeners[i]);
- it_from->_deathListeners[i] = 0;
- }
-}
-
-static void songit_tee_death_notification(TeeSongIterator *self, SongIterator *corpse) {
- if (corpse == self->_children[TEE_LEFT].it) {
- self->_status &= ~TEE_LEFT_ACTIVE;
- self->_children[TEE_LEFT].it = NULL;
- } else if (corpse == self->_children[TEE_RIGHT].it) {
- self->_status &= ~TEE_RIGHT_ACTIVE;
- self->_children[TEE_RIGHT].it = NULL;
- } else {
- error("songit_tee_death_notification() failed: Breakpoint in %s, line %d", __FILE__, __LINE__);
- }
-}
-
-TeeSongIterator::TeeSongIterator(SongIterator *left, SongIterator *right) {
- int i;
- int firstfree = 1; /* First free channel */
- int incomplete_map = 0;
-
- _readyToMorph = false;
- _status = TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE;
-
- _children[TEE_LEFT].it = left;
- _children[TEE_RIGHT].it = right;
-
- /* Default to lhs channels */
- channel_mask = left->channel_mask;
- for (i = 0; i < 16; i++)
- if (channel_mask & (1 << i) & right->channel_mask
- && (i != MIDI_RHYTHM_CHANNEL) /* Share rhythm */) { /*conflict*/
- while ((firstfree == MIDI_RHYTHM_CHANNEL)
- /* Either if it's the rhythm channel or if it's taken */
- || (firstfree < MIDI_CHANNELS
- && ((1 << firstfree) & channel_mask)))
- ++firstfree;
-
- if (firstfree == MIDI_CHANNELS) {
- incomplete_map = 1;
- //warning("[songit-tee <%08lx,%08lx>] Could not remap right channel #%d: Out of channels",
- // left->ID, right->ID, i);
- } else {
- _children[TEE_RIGHT].it->channel_remap[i] = firstfree;
-
- channel_mask |= (1 << firstfree);
- }
- }
-#ifdef DEBUG_TEE_ITERATOR
- if (incomplete_map) {
- int c;
- fprintf(stderr, "[songit-tee <%08lx,%08lx>] Channels:"
- " %04x <- %04x | %04x\n",
- left->ID, right->ID,
- channel_mask,
- left->channel_mask, right->channel_mask);
- for (c = 0 ; c < 2; c++)
- for (i = 0 ; i < 16; i++)
- fprintf(stderr, " map [%d][%d] -> %d\n",
- c, i, _children[c].it->channel_remap[i]);
- }
-#endif
-
-
- song_iterator_add_death_listener(left, this);
- song_iterator_add_death_listener(right, this);
-}
-
-TeeSongIterator::~TeeSongIterator() {
- // When we die, remove any listeners from our children
- if (_children[TEE_LEFT].it) {
- song_iterator_remove_death_listener(_children[TEE_LEFT].it, this);
- }
-
- if (_children[TEE_RIGHT].it) {
- song_iterator_remove_death_listener(_children[TEE_RIGHT].it, this);
- }
-}
-
-
-int TeeSongIterator::nextCommand(byte *buf, int *result) {
- static const int ready_masks[2] = {TEE_LEFT_READY, TEE_RIGHT_READY};
- static const int active_masks[2] = {TEE_LEFT_ACTIVE, TEE_RIGHT_ACTIVE};
- static const int pcm_masks[2] = {TEE_LEFT_PCM, TEE_RIGHT_PCM};
- int i;
- int retid;
-
-#ifdef DEBUG_TEE_ITERATOR
- fprintf(stderr, "[Tee] %02x\n", _status);
-#endif
-
- if (!(_status & (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE)))
- /* None is active? */
- return SI_FINISHED;
-
- if (_readyToMorph)
- return SI_MORPH;
-
- if ((_status & (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE))
- != (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE)) {
- /* Not all are is active? */
- int which = 0;
-#ifdef DEBUG_TEE_ITERATOR
- fprintf(stderr, "\tRequesting transformation...\n");
-#endif
- if (_status & TEE_LEFT_ACTIVE)
- which = TEE_LEFT;
- else if (_status & TEE_RIGHT_ACTIVE)
- which = TEE_RIGHT;
- memcpy(buf, _children[which].buf, sizeof(buf));
- *result = _children[which].result;
- _readyToMorph = true;
- return _children[which].retval;
- }
-
- /* First, check for unreported PCMs */
- for (i = TEE_LEFT; i <= TEE_RIGHT; i++)
- if ((_status & (ready_masks[i] | pcm_masks[i]))
- == (ready_masks[i] | pcm_masks[i])) {
- _status &= ~ready_masks[i];
- return SI_PCM;
- }
-
- for (i = TEE_LEFT; i <= TEE_RIGHT; i++)
- if (!(_status & ready_masks[i])) {
-
- /* Buffers aren't ready yet */
- _children[i].retval =
- songit_next(&(_children[i].it),
- _children[i].buf,
- &(_children[i].result),
- IT_READER_MASK_ALL
- | IT_READER_MAY_FREE
- | IT_READER_MAY_CLEAN);
-
- _status |= ready_masks[i];
-#ifdef DEBUG_TEE_ITERATOR
- fprintf(stderr, "\t Must check %d: %d\n", i, _children[i].retval);
-#endif
-
- if (_children[i].retval == SI_ABSOLUTE_CUE ||
- _children[i].retval == SI_RELATIVE_CUE)
- return _children[i].retval;
- if (_children[i].retval == SI_FINISHED) {
- _status &= ~active_masks[i];
- /* Recurse to complete */
-#ifdef DEBUG_TEE_ITERATOR
- fprintf(stderr, "\t Child %d signalled completion, recursing w/ status %02x\n", i, _status);
-#endif
- return nextCommand(buf, result);
- } else if (_children[i].retval == SI_PCM) {
- _status |= pcm_masks[i];
- _status &= ~ready_masks[i];
- return SI_PCM;
- }
- }
-
-
- /* We've already handled PCM, MORPH and FINISHED, CUEs & LOOP remain */
-
- retid = TEE_LEFT;
- if ((_children[TEE_LEFT].retval > 0)
- /* Asked to delay */
- && (_children[TEE_RIGHT].retval <= _children[TEE_LEFT].retval))
- /* Is not delaying or not delaying as much */
- retid = TEE_RIGHT;
-
-#ifdef DEBUG_TEE_ITERATOR
- fprintf(stderr, "\tl:%d / r:%d / chose %d\n",
- _children[TEE_LEFT].retval, _children[TEE_RIGHT].retval, retid);
-#endif
-
- /* Adjust delta times */
- if (_children[retid].retval > 0
- && _children[1-retid].retval > 0) {
- if (_children[1-retid].retval
- == _children[retid].retval)
- /* If both _children wait the same amount of time,
- ** we have to re-fetch commands from both */
- _status &= ~ready_masks[1-retid];
- else
- /* If they don't, we can/must re-use the other
- ** child's delay time */
- _children[1-retid].retval
- -= _children[retid].retval;
- }
-
- _status &= ~ready_masks[retid];
- memcpy(buf, _children[retid].buf, sizeof(buf));
- *result = _children[retid].result;
-
- return _children[retid].retval;
-}
-
-Audio::AudioStream *TeeSongIterator::getAudioStream() {
- static const int pcm_masks[2] = {TEE_LEFT_PCM, TEE_RIGHT_PCM};
- int i;
-
- for (i = TEE_LEFT; i <= TEE_RIGHT; i++)
- if (_status & pcm_masks[i]) {
- _status &= ~pcm_masks[i];
- return _children[i].it->getAudioStream();
- }
-
- return NULL; // No iterator
-}
-
-SongIterator *TeeSongIterator::handleMessage(Message msg) {
- if (msg._class == _SIMSG_PLASTICWRAP) {
- assert(msg._type == _SIMSG_PLASTICWRAP_ACK_MORPH);
-
- SongIterator *old_it;
- if (!(_status & (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE))) {
- delete this;
- return NULL;
- } else if (!(_status & TEE_LEFT_ACTIVE)) {
- delete _children[TEE_LEFT].it;
- _children[TEE_LEFT].it = 0;
- old_it = _children[TEE_RIGHT].it;
- song_iterator_remove_death_listener(old_it, this);
- song_iterator_transfer_death_listeners(old_it, this);
- delete this;
- return old_it;
- } else if (!(_status & TEE_RIGHT_ACTIVE)) {
- delete _children[TEE_RIGHT].it;
- _children[TEE_RIGHT].it = 0;
- old_it = _children[TEE_LEFT].it;
- song_iterator_remove_death_listener(old_it, this);
- song_iterator_transfer_death_listeners(old_it, this);
- delete this;
- return old_it;
- }
-
- warning("[tee-iterator] Morphing without need");
- return this;
- }
-
- if (msg._class == _SIMSG_BASE && msg._type == _SIMSG_BASEMSG_PRINT) {
- print_tabs_id(msg._arg.i, ID);
- debugC(2, kDebugLevelSound, "TEE:");
- msg._arg.i++;
- }
-
- // And continue with the children
- if (_children[TEE_LEFT].it)
- songit_handle_message(&(_children[TEE_LEFT].it), msg);
- if (_children[TEE_RIGHT].it)
- songit_handle_message(&(_children[TEE_RIGHT].it), msg);
-
- return NULL;
-}
-
-void TeeSongIterator::init() {
- _status = TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE;
- _children[TEE_LEFT].it->init();
- _children[TEE_RIGHT].it->init();
-}
-
-SongIterator *TeeSongIterator::clone(int delta) {
- TeeSongIterator *newit = new TeeSongIterator(*this);
-
- if (_children[TEE_LEFT].it)
- newit->_children[TEE_LEFT].it = _children[TEE_LEFT].it->clone(delta);
- if (_children[TEE_RIGHT].it)
- newit->_children[TEE_RIGHT].it = _children[TEE_RIGHT].it->clone(delta);
-
- return newit;
-}
-
-
-/*************************************/
-/*-- General purpose functionality --*/
-/*************************************/
-
-int songit_next(SongIterator **it, byte *buf, int *result, int mask) {
- int retval;
-
- if (!*it)
- return SI_FINISHED;
-
- do {
- retval = (*it)->nextCommand(buf, result);
- if (retval == SI_MORPH) {
- debugC(2, kDebugLevelSound, " Morphing %p (stored at %p)", (void *)*it, (void *)it);
- if (!SIMSG_SEND((*it), SIMSG_ACK_MORPH)) {
- error("SI_MORPH failed. Breakpoint in %s, line %d", __FILE__, __LINE__);
- } else
- debugC(2, kDebugLevelSound, "SI_MORPH successful");
- }
-
- if (retval == SI_FINISHED)
- debugC(2, kDebugLevelSound, "[song-iterator] Song finished. mask = %04x, cm=%04x",
- mask, (*it)->channel_mask);
- if (retval == SI_FINISHED
- && (mask & IT_READER_MAY_CLEAN)
- && (*it)->channel_mask) { /* This last test will fail
- ** with a terminated
- ** cleanup iterator */
- int channel_mask = (*it)->channel_mask;
-
- SongIterator *old_it = *it;
- *it = new CleanupSongIterator(channel_mask);
- for(uint i = 0; i < MIDI_CHANNELS; i++)
- (*it)->channel_remap[i] = old_it->channel_remap[i];
- song_iterator_transfer_death_listeners(*it, old_it);
- if (mask & IT_READER_MAY_FREE)
- delete old_it;
- retval = -9999; /* Continue */
- }
- } while (!( /* Until one of the following holds */
- (retval > 0 && (mask & IT_READER_MASK_DELAY))
- || (retval == 0 && (mask & IT_READER_MASK_MIDI))
- || (retval == SI_LOOP && (mask & IT_READER_MASK_LOOP))
- || (retval == SI_ABSOLUTE_CUE &&
- (mask & IT_READER_MASK_CUE))
- || (retval == SI_RELATIVE_CUE &&
- (mask & IT_READER_MASK_CUE))
- || (retval == SI_PCM && (mask & IT_READER_MASK_PCM))
- || (retval == SI_FINISHED)
- ));
-
- if (retval == SI_FINISHED && (mask & IT_READER_MAY_FREE)) {
- delete *it;
- *it = NULL;
- }
-
- return retval;
-}
-
-SongIterator::SongIterator() {
- ID = 0;
- channel_mask = 0;
- fade.action = FADE_ACTION_NONE;
- priority = 0;
- memset(_deathListeners, 0, sizeof(_deathListeners));
-
- // By default, don't remap
- for (uint i = 0; i < 16; i++)
- channel_remap[i] = i;
-}
-
-SongIterator::SongIterator(const SongIterator &si) {
- ID = si.ID;
- channel_mask = si.channel_mask;
- fade = si.fade;
- priority = si.priority;
- memset(_deathListeners, 0, sizeof(_deathListeners));
-
- for (uint i = 0; i < 16; i++)
- channel_remap[i] = si.channel_remap[i];
-}
-
-
-SongIterator::~SongIterator() {
- for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i)
- if (_deathListeners[i])
- songit_tee_death_notification(_deathListeners[i], this);
-}
-
-SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id) {
- BaseSongIterator *it;
-
- if (!data || size < 22) {
- warning("Attempt to instantiate song iterator for null song data");
- return NULL;
- }
-
-
- switch (type) {
- case SCI_SONG_ITERATOR_TYPE_SCI0:
- it = new Sci0SongIterator(data, size, id);
- break;
-
- case SCI_SONG_ITERATOR_TYPE_SCI1:
- it = new Sci1SongIterator(data, size, id);
- break;
-
- default:
- /**-- Invalid/unsupported sound resources --**/
- warning("Attempt to instantiate invalid/unknown song iterator type %d", type);
- return NULL;
- }
-
- return it;
-}
-
-int songit_handle_message(SongIterator **it_reg_p, SongIterator::Message msg) {
- SongIterator *it = *it_reg_p;
- SongIterator *newit;
-
- newit = it->handleMessage(msg);
-
- if (!newit)
- return 0; /* Couldn't handle */
-
- *it_reg_p = newit; /* Might have self-morphed */
- return 1;
-}
-
-SongIterator *sfx_iterator_combine(SongIterator *it1, SongIterator *it2) {
- if (it1 == NULL)
- return it2;
- if (it2 == NULL)
- return it1;
-
- /* Both are non-NULL: */
- return new TeeSongIterator(it1, it2);
-}
-
-} // End of namespace Sci
-
-#endif // USE_OLD_MUSIC_FUNCTIONS
diff --git a/engines/sci/sound/iterator/iterator.h b/engines/sci/sound/iterator/iterator.h
deleted file mode 100644
index e5c8f50702..0000000000
--- a/engines/sci/sound/iterator/iterator.h
+++ /dev/null
@@ -1,326 +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$
- *
- */
-
-/* Song iterator declarations */
-
-#ifndef SCI_SFX_SFX_ITERATOR_H
-#define SCI_SFX_SFX_ITERATOR_H
-
-#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-#include "sci/sound/drivers/mididriver.h"
-
-namespace Audio {
- class AudioStream;
-}
-
-namespace Sci {
-
-enum SongIteratorStatus {
- SI_FINISHED = -1, /**< Song finished playing */
- SI_LOOP = -2, /**< Song just looped */
- SI_ABSOLUTE_CUE = -3, /**< Found a song cue (absolute) */
- SI_RELATIVE_CUE = -4, /**< Found a song cue (relative) */
- SI_PCM = -5, /**< Found a PCM */
- SI_IGNORE = -6, /**< This event got edited out by the remapper */
- SI_MORPH = -255 /**< Song iterator requested self-morph. */
-};
-
-#define FADE_ACTION_NONE 0
-#define FADE_ACTION_FADE_AND_STOP 1
-#define FADE_ACTION_FADE_AND_CONT 2
-
-struct fade_params_t {
- int ticks_per_step;
- int final_volume;
- int step_size;
- int action;
-};
-
-/* Helper defs for messages */
-enum {
- _SIMSG_BASE, /* Any base decoder */
- _SIMSG_PLASTICWRAP /* Any "Plastic" (discardable) wrapper decoder */
-};
-
-/* Base messages */
-enum {
- _SIMSG_BASEMSG_SET_LOOPS, /* Set loops */
- _SIMSG_BASEMSG_SET_PLAYMASK, /* Set the current playmask for filtering */
- _SIMSG_BASEMSG_SET_RHYTHM, /* Activate/deactivate rhythm channel */
- _SIMSG_BASEMSG_ACK_MORPH, /* Acknowledge self-morph */
- _SIMSG_BASEMSG_STOP, /* Stop iterator */
- _SIMSG_BASEMSG_PRINT, /* Print self to stderr, after printing param1 tabs */
- _SIMSG_BASEMSG_SET_HOLD, /* Set value of hold parameter to expect */
- _SIMSG_BASEMSG_SET_FADE /* Set fade parameters */
-};
-
-/* "Plastic" (discardable) wrapper messages */
-enum {
- _SIMSG_PLASTICWRAP_ACK_MORPH = _SIMSG_BASEMSG_ACK_MORPH /* Acknowledge self-morph */
-};
-
-/* Messages */
-#define SIMSG_SET_LOOPS(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_LOOPS,(x)
-#define SIMSG_SET_PLAYMASK(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_PLAYMASK,(x)
-#define SIMSG_SET_RHYTHM(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_RHYTHM,(x)
-#define SIMSG_ACK_MORPH _SIMSG_PLASTICWRAP,_SIMSG_PLASTICWRAP_ACK_MORPH,0
-#define SIMSG_STOP _SIMSG_BASE,_SIMSG_BASEMSG_STOP,0
-#define SIMSG_PRINT(indentation) _SIMSG_BASE,_SIMSG_BASEMSG_PRINT,(indentation)
-#define SIMSG_SET_HOLD(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_HOLD,(x)
-
-/* Message transmission macro: Takes song reference, message reference */
-#define SIMSG_SEND(o, m) songit_handle_message(&(o), SongIterator::Message((o)->ID, m))
-#define SIMSG_SEND_FADE(o, m) songit_handle_message(&(o), SongIterator::Message((o)->ID, _SIMSG_BASE, _SIMSG_BASEMSG_SET_FADE, m))
-
-typedef unsigned long songit_id_t;
-
-
-#define SONGIT_MAX_LISTENERS 2
-
-class TeeSongIterator;
-
-class SongIterator {
-public:
- struct Message {
- songit_id_t ID;
- uint _class; /* Type of iterator supposed to receive this */
- uint _type;
- union {
- uint i;
- void *p;
- } _arg;
-
- Message() : ID(0), _class(0xFFFF), _type(0xFFFF) {}
-
- /**
- * Create a song iterator message.
- *
- * @param id: song ID the message is targeted to
- * @param recipient_class: Message recipient class
- * @param type message type
- * @param a argument
- *
- * @note You should only use this with the SIMSG_* macros
- */
- Message(songit_id_t id, int recipient_class, int type, int a)
- : ID(id), _class(recipient_class), _type(type) {
- _arg.i = a;
- }
-
- /**
- * Create a song iterator message, wherein the first parameter is a pointer.
- *
- * @param id: song ID the message is targeted to
- * @param recipient_class: Message recipient class
- * @param type message type
- * @param a argument
- *
- * @note You should only use this with the SIMSG_* macros
- */
- Message(songit_id_t id, int recipient_class, int type, void *a)
- : ID(id), _class(recipient_class), _type(type) {
- _arg.p = a;
- }
- };
-
-public:
- songit_id_t ID;
- uint16 channel_mask; /* Bitmask of all channels this iterator will use */
- fade_params_t fade;
- int priority;
-
- /* Death listeners */
- /* These are not reset during initialisation */
- TeeSongIterator *_deathListeners[SONGIT_MAX_LISTENERS];
-
- /* See songit_* for the constructor and non-virtual member functions */
-
- byte channel_remap[MIDI_CHANNELS]; ///< Remapping for channels
-
-public:
- SongIterator();
- SongIterator(const SongIterator &);
- virtual ~SongIterator();
-
- /**
- * Resets/initializes the sound iterator.
- */
- virtual void init() {}
-
- /**
- * Reads the next MIDI operation _or_ delta time.
- * @param buf The buffer to write to (needs to be able to store at least 4 bytes)
- * @param result Number of bytes written to the buffer
- * (equals the number of bytes that need to be passed
- * to the lower layers) for 0, the cue value for SI_CUE,
- * or the number of loops remaining for SI_LOOP.
- * @return zero if a MIDI operation was written, SI_FINISHED
- * if the song has finished playing, SI_LOOP if looping
- * (after updating the loop variable), SI_CUE if we found
- * a cue, SI_PCM if a PCM was found, or the number of ticks
- * to wait before this function should be called next.
- *
- * @note If SI_PCM is returned, get_pcm() may be used to retrieve the associated
- * PCM, but this must be done before any subsequent calls to next().
- *
- * @todo The actual buffer size should either be specified or passed in, so that
- * we can detect buffer overruns.
- */
- virtual int nextCommand(byte *buf, int *result) = 0;
-
- /**
- Checks for the presence of a pcm sample.
- * @return NULL if no PCM data was found, an AudioStream otherwise.
- */
- virtual Audio::AudioStream *getAudioStream() = 0;
-
- /**
- * Handles a message to the song iterator.
- * @param msg the message to handle
- * @return NULL if the message was not understood,
- * this if the message could be handled, or a new song iterator
- * if the current iterator had to be morphed (but the message could
- * still be handled)
- *
- * @note This function is not supposed to be called directly; use
- * songit_handle_message() instead. It should not recurse, since songit_handle_message()
- * takes care of that and makes sure that its delegate received the message (and
- * was morphed) before self.
- */
- virtual SongIterator *handleMessage(Message msg) = 0;
-
- /**
- * Gets the song position to store in a savegame.
- */
- virtual int getTimepos() = 0;
-
- /**
- * Clone this song iterator.
- * @param delta number of ticks that still need to elapse until the
- * next item should be read from the song iterator
- */
- virtual SongIterator *clone(int delta) = 0;
-
-
-private:
- // Make the assignment operator unreachable, just in case...
- SongIterator& operator=(const SongIterator&);
-};
-
-
-/********************************/
-/*-- Song iterator operations --*/
-/********************************/
-
-enum SongIteratorType {
- SCI_SONG_ITERATOR_TYPE_SCI0 = 0,
- SCI_SONG_ITERATOR_TYPE_SCI1 = 1
-};
-
-#define IT_READER_MASK_MIDI (1 << 0)
-#define IT_READER_MASK_DELAY (1 << 1)
-#define IT_READER_MASK_LOOP (1 << 2)
-#define IT_READER_MASK_CUE (1 << 3)
-#define IT_READER_MASK_PCM (1 << 4)
-#define IT_READER_MAY_FREE (1 << 10) /* Free SI_FINISHED iterators */
-#define IT_READER_MAY_CLEAN (1 << 11)
-/* MAY_CLEAN: May instantiate cleanup iterators
-** (use for players; this closes open channels at the end of a song) */
-
-#define IT_READER_MASK_ALL ( IT_READER_MASK_MIDI \
- | IT_READER_MASK_DELAY \
- | IT_READER_MASK_LOOP \
- | IT_READER_MASK_CUE \
- | IT_READER_MASK_PCM )
-
-/* Convenience wrapper around it->next
-** Parameters: (SongIterator **it) Reference to the iterator to access
-** (byte *) buf: The buffer to write to (needs to be able to
-** store at least 4 bytes)
-** (int) mask: IT_READER_MASK options specifying the events to
-** listen for
-** Returns : (int) zero if a MIDI operation was written, SI_FINISHED
-** if the song has finished playing, SI_LOOP if looping
-** (after updating the loop variable), SI_CUE if we found
-** a cue, SI_PCM if a PCM was found, or the number of ticks
-** to wait before this function should be called next.
-** (int) *result: Number of bytes written to the buffer
-** (equals the number of bytes that need to be passed
-** to the lower layers) for 0, the cue value for SI_CUE,
-** or the number of loops remaining for SI_LOOP.
-*/
-int songit_next(SongIterator **it, byte *buf, int *result, int mask);
-
-/* Constructs a new song iterator object
-** Parameters: (byte *) data: The song data to iterate over
-** (uint) size: Number of bytes in the song
-** (int) type: One of the SCI_SONG_ITERATOR_TYPEs
-** (songit_id_t) id: An ID for addressing the song iterator
-** Returns : (SongIterator *) A newly allocated but uninitialized song
-** iterator, or NULL if 'type' was invalid or unsupported
-*/
-SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id);
-
-/* Constructs a new song timer iterator object
-** Parameters: (int) delta: The delta after which to fire SI_FINISHED
-** Returns : (SongIterator *) A newly allocated but uninitialized song
-** iterator
-*/
-SongIterator *new_timer_iterator(int delta);
-
-/* Handles a message to the song iterator
-** Parameters: (SongIterator **): A reference to the variable storing the song iterator
-** Returns : (int) Non-zero if the message was understood
-** The song iterator may polymorph as result of msg, so a writeable reference is required.
-*/
-int songit_handle_message(SongIterator **it_reg, SongIterator::Message msg);
-
-
-/* Creates a new song iterator which fast-forwards
-** Parameters: (SongIterator *) it: The iterator to wrap
-** (int) delta: The number of ticks to skip
-** Returns : (SongIterator) A newly created song iterator
-** which skips all delta times
-** until 'delta' has been used up
-*/
-SongIterator *new_fast_forward_iterator(SongIterator *it, int delta);
-
-/* Combines two song iterators into one
-** Parameters: (sfx_iterator_t *) it1: One of the two iterators, or NULL
-** (sfx_iterator_t *) it2: The other iterator, or NULL
-** Returns : (sfx_iterator_t *) A combined iterator
-** If a combined iterator is returned, it will be flagged to be allowed to
-** dispose of 'it1' and 'it2', where applicable. This means that this
-** call should be used by song players, but not by the core sound system
-*/
-SongIterator *sfx_iterator_combine(SongIterator *it1, SongIterator *it2);
-
-} // End of namespace Sci
-
-#endif // USE_OLD_MUSIC_FUNCTIONS
-
-#endif // SCI_SFX_SFX_ITERATOR_H
diff --git a/engines/sci/sound/iterator/iterator_internal.h b/engines/sci/sound/iterator/iterator_internal.h
deleted file mode 100644
index 5a0f0d3ec9..0000000000
--- a/engines/sci/sound/iterator/iterator_internal.h
+++ /dev/null
@@ -1,276 +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_SFX_SFX_ITERATOR_INTERNAL
-#define SCI_SFX_SFX_ITERATOR_INTERNAL
-
-#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-#include "sci/sound/iterator/iterator.h"
-#include "sci/sound/drivers/mididriver.h"
-
-#include "common/array.h"
-#include "common/list.h"
-
-namespace Sci {
-
-/* Iterator types */
-
-enum {
- SI_STATE_UNINITIALISED = -1,
- SI_STATE_DELTA_TIME = 0, ///< Now at a delta time
- SI_STATE_COMMAND = 1, ///< Now at a MIDI operation
- SI_STATE_PENDING = 2, ///< Pending for loop
- SI_STATE_FINISHED = 3, ///< End of song
- SI_STATE_PCM = 4, ///< Should report a PCM next (-> DELTA_TIME)
- SI_STATE_PCM_MAGIC_DELTA = 5 ///< Should report a ``magic'' one tick delta time next (goes on to FINISHED)
-};
-
-struct SongIteratorChannel {
-
- int state; ///< State of this song iterator channel
- int offset; ///< Offset into the data chunk */
- int end; ///< Last allowed byte in track */
- int id; ///< Some channel ID */
-
- /**
- * Number of ticks before the specified channel is next used, or
- * CHANNEL_DELAY_MISSING to indicate that the delay has not yet
- * been read.
- */
- int delay;
-
- /* Two additional offsets for recovering: */
- int loop_offset;
- int initial_offset;
-
- int playmask; ///< Active playmask (MIDI channels to play in here) */
- int loop_timepos; ///< Total delay for this channel's loop marker */
- int total_timepos; ///< Number of ticks since the beginning, ignoring loops */
- int timepos_increment; ///< Number of ticks until the next command (to add) */
-
- byte last_cmd; ///< Last operation executed, for running status */
-
-public:
- void init(int id, int offset, int end);
- void resetSynthChannels();
-};
-
-class BaseSongIterator : public SongIterator {
-public:
- int _polyphony[MIDI_CHANNELS]; ///< # of simultaneous notes on each
-
- int _ccc; ///< Cumulative cue counter, for those who need it
- byte _resetflag; ///< for 0x4C -- on DoSound StopSound, do we return to start?
- int _deviceId; ///< ID of the device we generating events for
- int _numActiveChannels; ///< Number of active channels
- Common::Array<byte> _data; ///< Song data
-
- int _loops; ///< Number of loops remaining
-
-public:
- BaseSongIterator(byte *data, uint size, songit_id_t id);
-
-protected:
- int parseMidiCommand(byte *buf, int *result, SongIteratorChannel *channel, int flags);
- int processMidi(byte *buf, int *result, SongIteratorChannel *channel, int flags);
-};
-
-/********************************/
-/*--------- SCI 0 --------------*/
-/********************************/
-
-class Sci0SongIterator : public BaseSongIterator {
-public:
- SongIteratorChannel _channel;
-
-public:
- Sci0SongIterator(byte *data, uint size, songit_id_t id);
-
- int nextCommand(byte *buf, int *result);
- Audio::AudioStream *getAudioStream();
- SongIterator *handleMessage(Message msg);
- void init();
- int getTimepos();
- SongIterator *clone(int delta);
-};
-
-
-/********************************/
-/*--------- SCI 1 --------------*/
-/********************************/
-
-
-struct Sci1Sample {
- /**
- * Time left-- initially, this is 'Sample point 1'.
- * After initialisation, it is 'sample point 1 minus the sample
- * point of the previous sample'
- */
- int delta;
- int size;
- bool announced; /* Announced for download (SI_PCM) */
- int rate;
- byte *_data;
-};
-
-class Sci1SongIterator : public BaseSongIterator {
-public:
- SongIteratorChannel _channels[MIDI_CHANNELS];
-
- /* Invariant: Whenever channels[i].delay == CHANNEL_DELAY_MISSING,
- ** channel_offset[i] points to a delta time object. */
-
- bool _initialised; /**!< Whether the MIDI channel setup has been initialised */
- int _numChannels; /**!< Number of channels actually used */
- Common::List<Sci1Sample> _samples;
- int _numLoopedChannels; /**!< Number of channels that are ready to loop */
-
- int _delayRemaining; /**!< Number of ticks that haven't been polled yet */
- int _hold;
-
-public:
- Sci1SongIterator(byte *data, uint size, songit_id_t id);
- ~Sci1SongIterator();
-
- int nextCommand(byte *buf, int *result);
- Audio::AudioStream *getAudioStream();
- SongIterator *handleMessage(Message msg);
- void init();
- int getTimepos();
- SongIterator *clone(int delta);
-
-private:
- int initSample(const int offset);
- int initSong();
-
- int getSmallestDelta() const;
-
- void updateDelta(int delta);
-
- /** Checks that none of the channels is waiting for its delta to be read */
- bool noDeltaTime() const;
-
- /** Determine the channel # of the next active event, or -1 */
- int getCommandIndex() const;
-};
-
-#define PLAYMASK_NONE 0x0
-
-/***************************/
-/*--------- Timer ---------*/
-/***************************/
-
-/**
- * A song iterator which waits a specified time and then fires
- * SI_FINISHED. Used by DoSound, where audio resources are played (SCI1)
- */
-class TimerSongIterator : public SongIterator {
-protected:
- int _delta; /**!< Remaining time */
-
-public:
- TimerSongIterator(int delta) : _delta(delta) {}
-
- int nextCommand(byte *buf, int *result);
- Audio::AudioStream *getAudioStream() { return NULL; }
- SongIterator *handleMessage(Message msg) { return NULL; }
- int getTimepos() { return 0; }
- SongIterator *clone(int delta) { return new TimerSongIterator(*this); }
-};
-
-/**********************************/
-/*--------- Fast Forward ---------*/
-/**********************************/
-
-/**
- * A song iterator which fast-forwards another iterator.
- * Skips all delta times until a specified 'delta' has been used up.
- */
-class FastForwardSongIterator : public SongIterator {
-protected:
- SongIterator *_delegate;
- int _delta; /**!< Remaining time */
-
-public:
- FastForwardSongIterator(SongIterator *capsit, int delta);
-
- int nextCommand(byte *buf, int *result);
- Audio::AudioStream *getAudioStream();
- SongIterator *handleMessage(Message msg);
- int getTimepos();
- SongIterator *clone(int delta);
-};
-
-
-/**********************************/
-/*--------- Tee iterator ---------*/
-/**********************************/
-
-enum {
- TEE_LEFT = 0,
- TEE_RIGHT = 1,
- TEE_LEFT_ACTIVE = (1<<0),
- TEE_RIGHT_ACTIVE = (1<<1),
- TEE_LEFT_READY = (1<<2), /**!< left result is ready */
- TEE_RIGHT_READY = (1<<3), /**!< right result is ready */
- TEE_LEFT_PCM = (1<<4),
- TEE_RIGHT_PCM = (1<<5)
-};
-
-/**
- * This iterator combines two iterators, returns the next event available from either.
- */
-class TeeSongIterator : public SongIterator {
-public:
- int _status;
-
- bool _readyToMorph; /**!< One of TEE_MORPH_* above */
-
- struct {
- SongIterator *it;
- byte buf[4];
- int result;
- int retval;
- } _children[2];
-
-public:
- TeeSongIterator(SongIterator *left, SongIterator *right);
- ~TeeSongIterator();
-
- int nextCommand(byte *buf, int *result);
- Audio::AudioStream *getAudioStream();
- SongIterator *handleMessage(Message msg);
- void init();
- int getTimepos() { return 0; }
- SongIterator *clone(int delta);
-};
-
-} // End of namespace Sci
-
-#endif // USE_OLD_MUSIC_FUNCTIONS
-
-#endif // SCI_SFX_SFX_ITERATOR_INTERNAL
diff --git a/engines/sci/sound/iterator/songlib.cpp b/engines/sci/sound/iterator/songlib.cpp
deleted file mode 100644
index 8bc2e8f476..0000000000
--- a/engines/sci/sound/iterator/songlib.cpp
+++ /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$
- *
- */
-
-#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
-
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-#include "sci/sound/iterator/core.h"
-#include "sci/sound/iterator/iterator.h"
-
-namespace Sci {
-
-#define debug_stream stderr
-
-Song::Song() : _wakeupTime(0, SFX_TICKS_PER_SEC) {
- _handle = 0;
- _resourceNum = 0;
- _priority = 0;
- _status = SOUND_STATUS_STOPPED;
-
- _restoreBehavior = RESTORE_BEHAVIOR_CONTINUE;
- _restoreTime = 0;
-
- _loops = 0;
- _hold = 0;
-
- _it = 0;
- _delay = 0;
-
- _next = NULL;
- _nextPlaying = NULL;
- _nextStopping = NULL;
-}
-
-Song::Song(SongHandle handle, SongIterator *it, int priority) : _wakeupTime(0, SFX_TICKS_PER_SEC) {
- _handle = handle;
- _resourceNum = 0;
- _priority = priority;
- _status = SOUND_STATUS_STOPPED;
-
- _restoreBehavior = RESTORE_BEHAVIOR_CONTINUE;
- _restoreTime = 0;
-
- _loops = 0;
- _hold = 0;
-
- _it = it;
- _delay = 0;
-
- _next = NULL;
- _nextPlaying = NULL;
- _nextStopping = NULL;
-}
-
-void SongLibrary::addSong(Song *song) {
- Song **seeker = NULL;
- int pri = song->_priority;
-
- if (NULL == song) {
- warning("addSong(): NULL passed for song");
- return;
- }
-
- seeker = &_lib;
- while (*seeker && ((*seeker)->_priority > pri))
- seeker = &((*seeker)->_next);
-
- song->_next = *seeker;
- *seeker = song;
-}
-
-void SongLibrary::freeSounds() {
- Song *next = _lib;
- while (next) {
- Song *song = next;
- delete song->_it;
- song->_it = NULL;
- next = song->_next;
- delete song;
- }
- _lib = NULL;
-}
-
-
-Song *SongLibrary::findSong(SongHandle handle) {
- Song *seeker = _lib;
-
- while (seeker) {
- if (seeker->_handle == handle)
- break;
- seeker = seeker->_next;
- }
-
- return seeker;
-}
-
-Song *SongLibrary::findNextActive(Song *other) {
- Song *seeker = other ? other->_next : _lib;
-
- while (seeker) {
- if ((seeker->_status == SOUND_STATUS_WAITING) ||
- (seeker->_status == SOUND_STATUS_PLAYING))
- break;
- seeker = seeker->_next;
- }
-
- /* Only return songs that have equal priority */
- if (other && seeker && other->_priority > seeker->_priority)
- return NULL;
-
- return seeker;
-}
-
-Song *SongLibrary::findFirstActive() {
- return findNextActive(NULL);
-}
-
-int SongLibrary::removeSong(SongHandle handle) {
- int retval;
- Song *goner = _lib;
-
- if (!goner)
- return -1;
-
- if (goner->_handle == handle)
- _lib = goner->_next;
-
- else {
- while ((goner->_next) && (goner->_next->_handle != handle))
- goner = goner->_next;
-
- if (goner->_next) { /* Found him? */
- Song *oldnext = goner->_next;
-
- goner->_next = goner->_next->_next;
- goner = oldnext;
- } else return -1; /* No. */
- }
-
- retval = goner->_status;
-
- delete goner->_it;
- delete goner;
-
- return retval;
-}
-
-int SongLibrary::countSongs() {
- Song *seeker = _lib;
- int retval = 0;
-
- while (seeker) {
- retval++;
- seeker = seeker->_next;
- }
-
- return retval;
-}
-
-void SongLibrary::setSongRestoreBehavior(SongHandle handle, RESTORE_BEHAVIOR action) {
- Song *seeker = findSong(handle);
-
- seeker->_restoreBehavior = action;
-}
-
-} // End of namespace Sci
-
-#endif // USE_OLD_MUSIC_FUNCTIONS
diff --git a/engines/sci/sound/iterator/songlib.h b/engines/sci/sound/iterator/songlib.h
deleted file mode 100644
index acb704edaa..0000000000
--- a/engines/sci/sound/iterator/songlib.h
+++ /dev/null
@@ -1,171 +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$
- *
- */
-
-/* Song library */
-
-#ifndef SCI_SFX_SFX_SONGLIB_H
-#define SCI_SFX_SFX_SONGLIB_H
-
-#include "common/scummsys.h"
-#include "sound/timestamp.h"
-
-#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS
-#ifdef USE_OLD_MUSIC_FUNCTIONS
-
-namespace Sci {
-
-class SongIterator;
-
-#define SOUND_STATUS_STOPPED 0
-#define SOUND_STATUS_PLAYING 1
-#define SOUND_STATUS_SUSPENDED 2
-/* suspended: only if ordered from kernel space */
-#define SOUND_STATUS_WAITING 3
-/* "waiting" means "tagged for playing, but not active right now" */
-
-typedef unsigned long SongHandle;
-
-enum RESTORE_BEHAVIOR {
- RESTORE_BEHAVIOR_CONTINUE, /* restart a song when restored from
- a saved game */
- RESTORE_BEHAVIOR_RESTART /* continue it from where it was */
-};
-
-class Song {
-public:
- SongHandle _handle;
- int _resourceNum; /**<! Resource number */
- int _priority; /**!< Song priority (more important if priority is higher) */
- int _status; /* See above */
-
- int _restoreBehavior;
- int _restoreTime;
-
- /* Grabbed from the sound iterator, for save/restore purposes */
- int _loops;
- int _hold;
-
- SongIterator *_it;
- int _delay; /**!< Delay before accessing the iterator, in ticks */
-
- Audio::Timestamp _wakeupTime; /**!< Timestamp indicating the next MIDI event */
-
- Song *_next; /**!< Next song or NULL if this is the last one */
-
- /**
- * Next playing song. Used by the core song system.
- */
- Song *_nextPlaying;
-
- /**
- * Next song pending stopping. Used exclusively by the core song system's
- * _update_multi_song()
- */
- Song *_nextStopping;
-
-public:
-
- Song();
-
- /**
- * Initializes a new song.
- * @param handle the sound handle
- * @param it the song
- * @param priority the song's priority
- * @return a freshly allocated song
- */
- Song(SongHandle handle, SongIterator *it, int priority);
-};
-
-
-class SongLibrary {
-public:
- Song *_lib;
-
-public:
- SongLibrary() : _lib(0) {}
-
- /** Frees a song library. */
- void freeSounds();
-
- /**
- * Adds a song to a song library.
- * @param song song to add
- */
- void addSong(Song *song);
-
- /**
- * Looks up the song with the specified handle.
- * @param handle sound handle to look for
- * @return the song or NULL if it wasn't found
- */
- Song *findSong(SongHandle handle);
-
- /**
- * Finds the first song playing with the highest priority.
- * @return the song that should be played next, or NULL if there is none
- */
- Song *findFirstActive();
-
- /**
- * Finds the next song playing with the highest priority.
- *
- * The functions 'findFirstActive' and 'findNextActive'
- * allow to iterate over all songs that satisfy the requirement of
- * being 'playable'.
- *
- * @param song a song previously returned from the song library
- * @return the next song to play relative to 'song', or NULL if none are left
- */
- Song *findNextActive(Song *song);
-
- /**
- * Removes a song from the library.
- * @param handle handle of the song to remove
- * @return the status of the song that was removed
- */
- int removeSong(SongHandle handle);
-
- /**
- * Counts the number of songs in a song library.
- * @return the number of songs
- */
- int countSongs();
-
- /**
- * Determines what should be done with the song "handle" when restoring
- * it from a saved game.
- * @param handle sound handle being restored
- * @param action desired action
- */
- void setSongRestoreBehavior(SongHandle handle,
- RESTORE_BEHAVIOR action);
-};
-
-} // End of namespace Sci
-
-#endif // USE_OLD_MUSIC_FUNCTIONS
-
-#endif // SCI_SSFX_SFX_SONGLIB_H
diff --git a/engines/sci/sound/iterator/test-iterator.cpp b/engines/sci/sound/iterator/test-iterator.cpp
deleted file mode 100644
index 0d603a89fd..0000000000
--- a/engines/sci/sound/iterator/test-iterator.cpp
+++ /dev/null
@@ -1,423 +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 "iterator.h"
-#include "iterator_internal.h"
-#include <stdarg.h>
-#include <stdio.h>
-
-using namespace Sci;
-
-#define ASSERT_S(x) if (!(x)) { error("Failed assertion in L%d: " #x, __LINE__); return; }
-#define ASSERT(x) ASSERT_S(x)
-
-/* Tests the song iterators */
-
-int errors = 0;
-
-void error(char *fmt, ...) {
- va_list ap;
-
- fprintf(stderr, "[ERROR] ");
- va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
- va_end(ap);
-
- ++errors;
-}
-
-
-/* The simple iterator will finish after a fixed amount of time. Before that,
-** it emits (absolute) cues in ascending order. */
-struct simple_iterator : public SongIterator {
- int lifetime_remaining;
- char *cues;
- int cue_counter;
- int cue_progress;
- int cues_nr;
-};
-
-int simple_it_next(SongIterator *_self, unsigned char *buf, int *result) {
- simple_iterator *self = (simple_iterator *)_self;
-
- if (self->lifetime_remaining == -1) {
- error("Song iterator called post mortem");
- return SI_FINISHED;
- }
-
- if (self->lifetime_remaining) {
-
- if (self->cue_counter < self->cues_nr) {
- int time_to_cue = self->cues[self->cue_counter];
-
- if (self->cue_progress == time_to_cue) {
- ++self->cue_counter;
- self->cue_progress = 0;
- *result = self->cue_counter;
- return SI_ABSOLUTE_CUE;
- } else {
- int retval = time_to_cue - self->cue_progress;
- self->cue_progress = time_to_cue;
-
- if (retval > self->lifetime_remaining) {
- retval = self->lifetime_remaining;
- self->lifetime_remaining = 0;
- self->cue_progress = retval;
- return retval;
- }
-
- self->lifetime_remaining -= retval;
- return retval;
- }
- } else {
- int retval = self->lifetime_remaining;
- self->lifetime_remaining = 0;
- return retval;
- }
-
- } else {
- self->lifetime_remaining = -1;
- return SI_FINISHED;
- }
-}
-
-Audio::AudioStream *simple_it_pcm_feed(SongIterator *_self) {
- error("No PCM feed");
- return NULL;
-}
-
-void simple_it_init(SongIterator *_self) {
-}
-
-SongIterator *simple_it_handle_message(SongIterator *_self, SongIterator::Message msg) {
- return NULL;
-}
-
-void simple_it_cleanup(SongIterator *_self) {
-}
-
-/* Initialises the simple iterator.
-** Parameters: (int) delay: Number of ticks until the iterator finishes
-** (int *) cues: An array of cue delays (cue values are [1,2...])
-** (int) cues_nr: Number of cues in ``cues''
-** The first cue is emitted after cues[0] ticks, and it is 1. After cues[1] additional ticks
-** the next cue is emitted, and so on. */
-SongIterator *setup_simple_iterator(int delay, char *cues, int cues_nr) {
- simple_iterator.lifetime_remaining = delay;
- simple_iterator.cues = cues;
- simple_iterator.cue_counter = 0;
- simple_iterator.cues_nr = cues_nr;
- simple_iterator.cue_progress = 0;
-
- simple_iterator.ID = 42;
- simple_iterator.channel_mask = 0x004f;
- simple_iterator.flags = 0;
- simple_iterator.priority = 1;
-
- simple_iterator.death_listeners_nr = 0;
-
- simple_iterator.cleanup = simple_it_cleanup;
- simple_iterator.init = simple_it_init;
- simple_iterator.handle_message = simple_it_handle_message;
- simple_iterator.get_pcm_feed = simple_it_pcm_feed;
- simple_iterator.next = simple_it_next;
-
- return (SongIterator *) &simple_iterator;
-}
-
-#define ASSERT_SIT ASSERT(it == simple_it)
-#define ASSERT_FFIT ASSERT(it == ff_it)
-#define ASSERT_NEXT(n) ASSERT(songit_next(&it, data, &result, IT_READER_MASK_ALL) == n)
-#define ASSERT_RESULT(n) ASSERT(result == n)
-#define ASSERT_CUE(n) ASSERT_NEXT(SI_ABSOLUTE_CUE); ASSERT_RESULT(n)
-
-void test_simple_it() {
- SongIterator *it;
- SongIterator *simple_it = (SongIterator *) & simple_iterator;
- unsigned char data[4];
- int result;
- puts("[TEST] simple iterator (test artifact)");
-
- it = setup_simple_iterator(42, NULL, 0);
-
- ASSERT_SIT;
- ASSERT_NEXT(42);
- ASSERT_SIT;
- ASSERT_NEXT(SI_FINISHED);
- ASSERT_SIT;
-
- it = setup_simple_iterator(42, "\003\004", 2);
- ASSERT_SIT;
- ASSERT_NEXT(3);
- ASSERT_CUE(1);
- ASSERT_SIT;
- ASSERT_NEXT(4);
- ASSERT_CUE(2);
- ASSERT_SIT;
-// warning("XXX => %d", songit_next(&it, data, &result, IT_READER_MASK_ALL));
- ASSERT_NEXT(35);
- ASSERT_NEXT(SI_FINISHED);
- ASSERT_SIT;
-
- puts("[TEST] Test OK.");
-}
-
-void test_fastforward() {
- SongIterator *it;
- SongIterator *simple_it = (SongIterator *) & simple_iterator;
- SongIterator *ff_it;
- unsigned char data[4];
- int result;
- puts("[TEST] fast-forward iterator");
-
- it = setup_simple_iterator(42, NULL, 0);
- ff_it = it = new_fast_forward_iterator(it, 0);
- ASSERT_FFIT;
- ASSERT_NEXT(42);
- ASSERT_SIT; /* Must have morphed back */
- ASSERT_NEXT(SI_FINISHED);
- ASSERT_SIT;
-
- it = setup_simple_iterator(42, NULL, 0);
- ff_it = it = new_fast_forward_iterator(it, 1);
- ASSERT_FFIT;
- ASSERT_NEXT(41);
- /* May or may not have morphed back here */
- ASSERT_NEXT(SI_FINISHED);
- ASSERT_SIT;
-
- it = setup_simple_iterator(42, NULL, 0);
- ff_it = it = new_fast_forward_iterator(it, 41);
- ASSERT_FFIT;
- ASSERT_NEXT(1);
- /* May or may not have morphed back here */
- ASSERT_NEXT(SI_FINISHED);
- ASSERT_SIT;
-
- it = setup_simple_iterator(42, NULL, 0);
- ff_it = it = new_fast_forward_iterator(it, 42);
- ASSERT_NEXT(SI_FINISHED);
- /* May or may not have morphed back here */
-
- it = setup_simple_iterator(42, NULL, 0);
- ff_it = it = new_fast_forward_iterator(it, 10000);
- ASSERT_NEXT(SI_FINISHED);
- /* May or may not have morphed back here */
-
- it = setup_simple_iterator(42, "\003\004", 2);
- ff_it = it = new_fast_forward_iterator(it, 2);
- ASSERT_FFIT;
- ASSERT_NEXT(1);
- ASSERT_CUE(1);
- ASSERT_SIT;
- ASSERT_NEXT(4);
- ASSERT_CUE(2);
- ASSERT_SIT;
- ASSERT_NEXT(35);
- ASSERT_NEXT(SI_FINISHED);
- ASSERT_SIT;
-
- it = setup_simple_iterator(42, "\003\004", 2);
- ff_it = it = new_fast_forward_iterator(it, 5);
- ASSERT_FFIT;
- ASSERT_CUE(1);
- ASSERT_FFIT;
- ASSERT_NEXT(2);
- ASSERT_CUE(2);
- ASSERT_SIT;
- ASSERT_NEXT(35);
- ASSERT_NEXT(SI_FINISHED);
- ASSERT_SIT;
-
- it = setup_simple_iterator(42, "\003\004", 2);
- ff_it = it = new_fast_forward_iterator(it, 41);
- ASSERT_FFIT;
- ASSERT_CUE(1);
- ASSERT_FFIT;
- ASSERT_CUE(2);
- ASSERT_FFIT;
- ASSERT_NEXT(1);
- ASSERT_NEXT(SI_FINISHED);
- ASSERT_SIT;
-
- puts("[TEST] Test OK.");
-}
-
-#define SIMPLE_SONG_SIZE 50
-
-static unsigned char simple_song[SIMPLE_SONG_SIZE] = {
- 0x00, /* Regular song */
- /* Only use channel 0 for all devices */
- 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* Song begins here */
- 42, 0x90, 60, 0x7f, /* Play C after 42 ticks */
- 02, 64, 0x42, /* Play E after 2 more ticks, using running status mode */
- 0xf8, 10, 0x80, 60, 0x02, /* Stop C after 250 ticks */
- 0, 64, 0x00, /* Stop E immediately */
- 00, 0xfc /* Stop song */
-};
-
-#define ASSERT_MIDI3(cmd, arg0, arg1) \
- ASSERT(data[0] == cmd); \
- ASSERT(data[1] == arg0); \
- ASSERT(data[2] == arg1);
-
-void test_iterator_sci0() {
- SongIterator *it = songit_new(simple_song, SIMPLE_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l);
- unsigned char data[4];
- int result;
- SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */
-
- puts("[TEST] SCI0-style song");
- ASSERT_NEXT(42);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x90, 60, 0x7f);
- ASSERT_NEXT(2);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x90, 64, 0x42);
- ASSERT_NEXT(250);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x80, 60, 0x02);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x80, 64, 0x00);
- ASSERT_NEXT(SI_FINISHED);
- puts("[TEST] Test OK.");
-}
-
-
-
-void test_iterator_sci0_loop() {
- SongIterator *it = songit_new(simple_song, SIMPLE_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l);
- unsigned char data[4];
- int result;
- SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */
- SIMSG_SEND(it, SIMSG_SET_LOOPS(2)); /* Loop one additional time */
-
- puts("[TEST] SCI0-style song with looping");
- ASSERT_NEXT(42);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x90, 60, 0x7f);
- ASSERT_NEXT(2);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x90, 64, 0x42);
- ASSERT_NEXT(250);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x80, 60, 0x02);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x80, 64, 0x00);
- ASSERT_NEXT(SI_LOOP);
- ASSERT_NEXT(42);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x90, 60, 0x7f);
- ASSERT_NEXT(2);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x90, 64, 0x42);
- ASSERT_NEXT(250);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x80, 60, 0x02);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x80, 64, 0x00);
- ASSERT_NEXT(SI_FINISHED);
- puts("[TEST] Test OK.");
-}
-
-
-
-#define LOOP_SONG_SIZE 54
-
-unsigned char loop_song[LOOP_SONG_SIZE] = {
- 0x00, /* Regular song song */
- /* Only use channel 0 for all devices */
- 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* Song begins here */
- 42, 0x90, 60, 0x7f, /* Play C after 42 ticks */
- 13, 0x80, 60, 0x00, /* Stop C after 13 ticks */
- 00, 0xCF, 0x7f, /* Set loop point */
- 02, 0x90, 64, 0x42, /* Play E after 2 more ticks, using running status mode */
- 03, 0x80, 64, 0x00, /* Stop E after 3 ticks */
- 00, 0xfc /* Stop song/loop */
-};
-
-
-void test_iterator_sci0_mark_loop() {
- SongIterator *it = songit_new(loop_song, LOOP_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l);
- unsigned char data[4];
- int result;
- SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */
- SIMSG_SEND(it, SIMSG_SET_LOOPS(3)); /* Loop once more */
-
- puts("[TEST] SCI0-style song with loop mark, looping");
- ASSERT_NEXT(42);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x90, 60, 0x7f);
- ASSERT_NEXT(13);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x80, 60, 0x00);
- /* Loop point here: we don't observe that in the iterator interface yet, though */
- ASSERT_NEXT(2);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x90, 64, 0x42);
- ASSERT_NEXT(3);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x80, 64, 0x00);
- /* Now we loop back to the loop pont */
- ASSERT_NEXT(SI_LOOP);
- ASSERT_NEXT(2);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x90, 64, 0x42);
- ASSERT_NEXT(3);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x80, 64, 0x00);
- /* ...and one final time */
- ASSERT_NEXT(SI_LOOP);
- ASSERT_NEXT(2);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x90, 64, 0x42);
- ASSERT_NEXT(3);
- ASSERT_NEXT(0);
- ASSERT_MIDI3(0x80, 64, 0x00);
-
- ASSERT_NEXT(SI_FINISHED);
- puts("[TEST] Test OK.");
-}
-
-
-
-int main(int argc, char **argv) {
- test_simple_it();
- test_fastforward();
- test_iterator_sci0();
- test_iterator_sci0_loop();
- test_iterator_sci0_mark_loop();
- if (errors != 0)
- warning("[ERROR] %d errors total", errors);
- return (errors != 0);
-}
diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp
index 3ee8a3a83d..6ec28a8b02 100644
--- a/engines/sci/sound/midiparser_sci.cpp
+++ b/engines/sci/sound/midiparser_sci.cpp
@@ -43,30 +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;
-
- for (int i = 0; i < 16; i++)
- _channelRemap[i] = i;
+ _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) {
@@ -75,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
@@ -86,30 +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;
- 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;
@@ -118,36 +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 (isChannelUsed(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
}
}
- for (int i = 0; i < 16; i++)
- _channelRemap[i] = i;
+ // 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
- setChannelUsed(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;
@@ -173,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;
@@ -212,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:
@@ -235,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
@@ -249,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;
@@ -307,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;
@@ -319,254 +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 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;
- 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;
+ int i, j;
- 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;
-
- 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;
+ // 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);
}
- *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++;
-
- // TODO: Fix remapping
-
-#if 0
- // Remap channel. Keep the upper 4 bits (command code) and change
- // the lower 4 bits (channel)
- byte remappedChannel = _channelRemap[par1 & 0xF];
- par1 = (par1 & 0xF0) | (remappedChannel & 0xF);
-#endif
- } else {// running status
- par1 = command;
- command = channel->prev;
- }
- 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;
+ // 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;
}
- 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) {
- 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 9d4b5a39da..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,23 +76,29 @@ public:
jumpToTick(0);
}
- void remapChannel(byte channel, byte newChannel) {
- assert(channel < 0xF); // don't touch special SCI channel 15
- assert(newChannel < 0xF); // don't touch special SCI channel 15
- _channelRemap[channel] = newChannel;
- }
+ void allNotesOff();
- void clearUsedChannels() { _channelsUsed = 0; }
+ const byte *getMixedData() const { return _mixedData; }
-protected:
- bool isChannelUsed(byte channel) const { return _channelsUsed & (1 << channel); }
- void setChannelUsed(byte channel) { _channelsUsed |= (1 << channel); }
+ 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;
@@ -101,11 +112,10 @@ protected:
int16 _dataincToAdd;
bool _resetOnPause;
- // A 16-bit mask, containing the channels used
- // by the currently parsed song
- uint16 _channelsUsed;
-
- byte _channelRemap[16];
+ 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 fa5716e7cc..061f380ebc 100644
--- a/engines/sci/sound/music.cpp
+++ b/engines/sci/sound/music.cpp
@@ -43,6 +43,11 @@ SciMusic::SciMusic(SciVersion soundVersion)
// 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() {
@@ -58,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:
@@ -100,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() {
@@ -119,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);
@@ -160,6 +189,24 @@ 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);
@@ -174,28 +221,14 @@ void SciMusic::sortPlayList() {
Common::sort(_playList.begin(), _playList.end(), musicEntryCompare);
}
-void SciMusic::findUsedChannels() {
- // Reset list
- for (int k = 0; k < 16; k++)
- _usedChannels[k] = false;
-
- const MusicList::const_iterator end = _playList.end();
- for (MusicList::const_iterator i = _playList.begin(); i != end; ++i) {
- for (int channel = 0; channel < 16; channel++) {
- if ((*i)->soundRes && (*i)->soundRes->isChannelUsed(channel))
- _usedChannels[channel] = true;
- }
- }
-}
-
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)
@@ -224,49 +257,56 @@ 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);
}
pSnd->pauseCounter = 0;
- // TODO: Fix channel remapping. This doesn't quite work... (e.g. no difference in LSL1VGA)
-#if 0
- // Remap channels
- findUsedChannels();
-
- pSnd->pMidiParser->clearUsedChannels();
-
- for (int i = 0; i < 16; i++) {
- if (_usedChannels[i] && pSnd->soundRes->isChannelUsed(i)) {
- int16 newChannel = getNextUnusedChannel();
- if (newChannel >= 0) {
- _usedChannels[newChannel] = true;
- debug("Remapping channel %d to %d\n", i, newChannel);
- pSnd->pMidiParser->remapChannel(i, newChannel);
- } else {
- warning("Attempt to remap channel %d, but no unused channels exist", i);
- }
- }
- }
-#endif
-
// 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) {
@@ -294,7 +334,7 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
if ((_soundVersion <= SCI_VERSION_0_LATE) && (alreadyPlaying)) {
// Music already playing in SCI0?
if (pSnd->priority > alreadyPlaying->priority) {
- // And new priority higher? pause previous music and play new one immediately
+ // 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;
@@ -317,34 +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) {
@@ -353,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();
}
}
@@ -368,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);
@@ -406,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();
+ }
}
}
@@ -448,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);
@@ -516,7 +601,7 @@ MusicEntry::MusicEntry() {
priority = 0;
loop = 0;
volume = MUSIC_VOLUME_DEFAULT;
- hold = 0;
+ hold = -1;
pauseCounter = 0;
sampleLoopCounter = 0;
@@ -567,14 +652,6 @@ void MusicEntry::doFade() {
fadeStep = 0;
fadeCompleted = true;
}
-#ifdef ENABLE_SCI32
- // Disable fading for SCI32 - sound drivers have issues when fading in (gabriel knight 1 sierra title)
- if (getSciVersion() >= SCI_VERSION_2) {
- volume = fadeTo;
- fadeStep = 0;
- fadeCompleted = true;
- }
-#endif
// Only process MIDI streams in this thread, not digital sound effects
if (pMidiParser) {
diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h
index 83cd59e89b..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,6 +185,9 @@ public:
// where a deadlock can occur
Common::Mutex _mutex;
+ int16 tryToOwnChannel(MusicEntry *caller, int16 bestChannel);
+ void freeChannels(MusicEntry *caller);
+
protected:
void sortPlayList();
@@ -208,22 +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);
- void findUsedChannels();
- int16 getNextUnusedChannel() const {
- for (int i = 0; i < 16; i++) {
- if (!_usedChannels[i])
- return i;
- }
-
- return -1;
- }
+private:
MusicList _playList;
bool _soundOn;
byte _masterVolume;
- bool _usedChannels[16];
+ 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 ece4c1430c..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 = readSelectorValue(segMan, obj, SELECTOR(number));
- Resource *song = resMan->findResource(ResourceId(kResourceTypeSound, song_nr), 0);
- int flags = readSelectorValue(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);
- writeSelectorValue(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);
- /* writeSelectorValue(segMan, obj, SELECTOR(loops), readSelectorValue(segMan, obj, SELECTOR(loop));; - 1);*/
- writeSelectorValue(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);
- writeSelectorValue(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);
- writeSelectorValue(segMan, obj, SELECTOR(signal), cue);
- break;
-
- case SI_FINISHED:
- debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x finished",
- PRINT_REG(obj));
- writeSelectorValue(segMan, obj, SELECTOR(signal), SIGNAL_OFFSET);
- writeSelectorValue(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;
-
+void SoundCommandParser::processInitSound(reg_t obj) {
int resourceId = readSelectorValue(_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 (readSelectorValue(_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)
- writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundInitialized);
- else
- writeSelector(_segMan, obj, SELECTOR(nodePtr), obj);
-
- writeSelector(_segMan, obj, SELECTOR(handle), obj);
-
-#else
-
// 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;
@@ -307,6 +71,9 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) {
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
// effects. If the resource exists, play it using map 65535 (sound
@@ -333,98 +100,29 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) {
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, readSelectorValue(_segMan, obj, SELECTOR(loop)));
- writeSelectorValue(_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, readSelectorValue(_segMan, obj, SELECTOR(loop)));
- _state->sfx_song_renice(handle, readSelectorValue(_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);
- writeSelectorValue(_segMan, obj, SELECTOR(signal), 0);
- } else if (_soundVersion == SCI_VERSION_1_LATE) {
- int looping = readSelectorValue(_segMan, obj, SELECTOR(loop));
- //int vol = readSelectorValue(_segMan, obj, SELECTOR(vol));
- int pri = readSelectorValue(_segMan, obj, SELECTOR(pri));
- int sampleLen = 0;
- Song *song = _state->_songlib.findSong(handle);
- int songNumber = readSelectorValue(_segMan, obj, SELECTOR(number));
-
- if (readSelectorValue(_segMan, obj, SELECTOR(nodePtr)) && (song && songNumber != song->_resourceNum)) {
- _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED);
- _state->sfx_remove_song(handle);
- writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG);
- }
-
- if (!readSelectorValue(_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);
- writeSelectorValue(_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);
- }
-
- writeSelector(_segMan, obj, SELECTOR(nodePtr), obj);
- writeSelector(_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);
- writeSelectorValue(_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 ? 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 = readSelectorValue(_segMan, obj, SELECTOR(loop));
- debugC(2, kDebugLevelSound, "cmdPlaySound: resource number %d, loop %d", resourceId, loop);
writeSelector(_segMan, obj, SELECTOR(handle), obj);
@@ -442,51 +140,38 @@ void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) {
musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority));
if (_soundVersion >= SCI_VERSION_1_EARLY)
musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol));
- _music->soundPlay(musicSlot);
-#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)
- writeSelectorValue(_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)
- writeSelectorValue(_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);
writeSelectorValue(_segMan, obj, SELECTOR(handle), 0);
@@ -494,26 +179,18 @@ void SoundCommandParser::cmdDisposeSound(reg_t obj, int16 value) {
writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG);
else
writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped);
-#endif
}
-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)
- writeSelectorValue(_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;
}
@@ -523,204 +200,161 @@ void SoundCommandParser::processStopSound(reg_t obj, int16 value, bool sampleFin
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)
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()
- writeSelectorValue(_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());
}
- writeSelectorValue(_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) {
- /* 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)
- writeSelectorValue(_segMan, obj, SELECTOR(state), SOUND_STATUS_STOPPED);
- writeSelectorValue(_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()) {
- writeSelectorValue(_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.
- writeSelectorValue(_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");
- writeSelectorValue(_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, readSelectorValue(_segMan, obj, SELECTOR(loop)));
- script_set_priority(_resMan, _segMan, _state, obj, readSelectorValue(_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 = readSelectorValue(_segMan, obj, SELECTOR(loop));
@@ -730,88 +364,18 @@ void SoundCommandParser::cmdUpdateSound(reg_t obj, int16 value) {
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);
- writeSelectorValue(_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. */
- writeSelectorValue(_segMan, obj, SELECTOR(dataInc), signal);
- debugC(2, kDebugLevelSound, "rel-signal %04X", signal);
- if (_soundVersion == SCI_VERSION_1_EARLY)
- writeSelectorValue(_segMan, obj, SELECTOR(signal), signal);
- else
- writeSelectorValue(_segMan, obj, SELECTOR(signal), signal + 127);
- break;
-
- case SI_FINISHED:
- debugC(2, kDebugLevelSound, "--- [FINISHED] %04x:%04x", PRINT_REG(obj));
- writeSelectorValue(_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 != readSelectorValue(segMan, obj, SELECTOR(dataInc))) {
- // writeSelectorValue(segMan, obj, SELECTOR(dataInc), dataInc);
- // writeSelectorValue(segMan, obj, SELECTOR(signal), dataInc+0x7f);
- // } else {
- // writeSelectorValue(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 != readSelectorValue(segMan, obj, SELECTOR(dataInc))) {
- // writeSelectorValue(segMan, obj, SELECTOR(dataInc), dataInc);
- // writeSelectorValue(segMan, obj, SELECTOR(signal), dataInc + 0x7f);
- // } else {
- // writeSelectorValue(segMan, obj, SELECTOR(signal), signal);
- // }
- // break;
- //}
-
- if (_soundVersion == SCI_VERSION_1_EARLY) {
- writeSelectorValue(_segMan, obj, SELECTOR(min), min);
- writeSelectorValue(_segMan, obj, SELECTOR(sec), sec);
- writeSelectorValue(_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;
}
@@ -827,9 +391,13 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) {
musicSlot->loop -= currentLoopCounter - musicSlot->sampleLoopCounter;
musicSlot->sampleLoopCounter = currentLoopCounter;
}
- if ((!_music->soundIsActive(musicSlot)) && (musicSlot->status != kSoundPaused)) {
- 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,7 +409,7 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) {
// Update MIDI slots
if (musicSlot->signal == 0) {
if (musicSlot->dataInc != readSelectorValue(_segMan, obj, SELECTOR(dataInc))) {
- if (_kernel->_selectorCache.dataInc > -1)
+ if (SELECTOR(dataInc) > -1)
writeSelectorValue(_segMan, obj, SELECTOR(dataInc), musicSlot->dataInc);
writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->dataInc + 127);
}
@@ -850,13 +418,15 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) {
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
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 we don't set signal here, at least the switch to the mud wrestling
+ // room in lsl5 will not work.
}
if (musicSlot->fadeCompleted) {
@@ -864,10 +434,10 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) {
// We need signal for sci0 at least in iceman as well (room 14, fireworks)
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);
}
}
@@ -882,48 +452,72 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) {
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
+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;
+
Common::StackLock(_music->_mutex);
const MusicList::iterator end = _music->getPlayListEnd();
@@ -931,32 +525,31 @@ void SoundCommandParser::cmdStopAllSounds(reg_t obj, int16 value) {
if (_soundVersion <= SCI_VERSION_0_LATE) {
writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(state), kSoundStopped);
} else {
- writeSelectorValue(_segMan, obj, SELECTOR(handle), 0);
+ 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);
@@ -965,20 +558,19 @@ void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) {
_music->soundSetVolume(musicSlot, 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) {
@@ -987,7 +579,7 @@ 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
writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) & 0xFD);
@@ -998,32 +590,28 @@ void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) {
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 (!readSelector(_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;
@@ -1032,40 +620,37 @@ void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) {
}
writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop);
-#endif
+ 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
+ // 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
+ // 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()
@@ -1074,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 = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(dataInc));
- (*i)->signal = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(signal));
-
- if (_soundVersion >= SCI_VERSION_1_LATE)
- (*i)->volume = readSelectorValue(_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);
+ processDisposeSound(soundObj);
writeSelectorValue(_segMan, soundObj, SELECTOR(number), number);
- cmdInitSound(soundObj, 0);
- cmdPlaySound(soundObj, 0);
-#endif
+ 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
index 93132bc5d6..680a449207 100644
--- a/engines/sci/video/vmd_decoder.cpp
+++ b/engines/sci/video/vmd_decoder.cpp
@@ -50,13 +50,13 @@ VMDDecoder::~VMDDecoder() {
close();
}
-bool VMDDecoder::load(Common::SeekableReadStream &stream) {
+bool VMDDecoder::load(Common::SeekableReadStream *stream) {
close();
if (!_vmdDecoder->load(stream))
return false;
- _fileStream = &stream;
+ _fileStream = stream;
if (_vmdDecoder->getFeatures() & Graphics::CoktelVideo::kFeaturesPalette)
loadPaletteFromVMD();
diff --git a/engines/sci/video/vmd_decoder.h b/engines/sci/video/vmd_decoder.h
index 231da9202e..e79064b1f7 100644
--- a/engines/sci/video/vmd_decoder.h
+++ b/engines/sci/video/vmd_decoder.h
@@ -56,7 +56,7 @@ public:
uint32 getFrameWaitTime();
- bool load(Common::SeekableReadStream &stream);
+ bool load(Common::SeekableReadStream *stream);
void close();
bool isVideoLoaded() const { return _fileStream != 0; }
diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp
index 0e0c0e129e..fa4804ce7d 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 ea29e25a1f..b5a4070f0b 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("Current Passcode is %d \nUse 'passcode <SEGA CD Passcode>'\n",_vm->_scummVars[411]);
@@ -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 d9c24ddca2..1e0bf6d4be 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"
@@ -283,9 +284,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 cc382d9621..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 Mon May 24 13:24:24 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,6 +168,7 @@ 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 },
@@ -183,7 +185,7 @@ static const MD5Table md5table[] = {
{ "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 },
@@ -196,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 },
@@ -225,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 },
@@ -242,7 +246,7 @@ 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 },
@@ -357,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 },
@@ -366,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 },
@@ -413,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 },
@@ -430,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 },
@@ -489,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 },
@@ -519,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 },
@@ -554,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 },
@@ -576,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 },
@@ -617,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 bb50ce7bb2..fc95060b6f 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -1634,28 +1634,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:
@@ -1707,7 +1707,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");
}
@@ -1723,7 +1723,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) {
@@ -1735,11 +1737,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) {
@@ -1749,12 +1751,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);
}
@@ -1769,7 +1771,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) {
@@ -1840,8 +1842,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.
@@ -2081,6 +2082,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/testbed/config.cpp b/engines/testbed/config.cpp
index ae52b136d7..1cfb1bc395 100644
--- a/engines/testbed/config.cpp
+++ b/engines/testbed/config.cpp
@@ -61,12 +61,12 @@ TestbedOptionsDialog::TestbedOptionsDialog(Common::Array<Testsuite *> &tsList, T
_testListDisplay->setEditable(false);
if (selected > (tsList.size() - selected)) {
- _selectButton = new GUI::ButtonWidget(this, "Browser.Up", "Deselect All", kTestbedDeselectAll, 0);
+ _selectButton = new GUI::ButtonWidget(this, "Browser.Up", "Deselect All", 0, kTestbedDeselectAll, 0);
} else {
- _selectButton = new GUI::ButtonWidget(this, "Browser.Up", "Select All", kTestbedSelectAll, 0);
+ _selectButton = new GUI::ButtonWidget(this, "Browser.Up", "Select All", 0, kTestbedSelectAll, 0);
}
- new GUI::ButtonWidget(this, "Browser.Cancel", "Run tests", GUI::kCloseCmd);
- new GUI::ButtonWidget(this, "Browser.Choose", "Exit Testbed", kTestbedQuitCmd);
+ new GUI::ButtonWidget(this, "Browser.Cancel", "Run tests", 0, GUI::kCloseCmd);
+ new GUI::ButtonWidget(this, "Browser.Choose", "Exit Testbed", 0, kTestbedQuitCmd);
}
TestbedOptionsDialog::~TestbedOptionsDialog() {}
@@ -141,7 +141,7 @@ void TestbedInteractionDialog::addButton(uint w, uint h, const Common::String na
xOffset = _xOffset;
}
_yOffset += yPadding;
- _buttonArray.push_back(new GUI::ButtonWidget(this, xOffset, _yOffset, w, h, name, cmd));
+ _buttonArray.push_back(new GUI::ButtonWidget(this, xOffset, _yOffset, w, h, name, 0, cmd));
_yOffset += h;
}
@@ -155,7 +155,7 @@ void TestbedInteractionDialog::addList(uint x, uint y, uint w, uint h, Common::A
}
void TestbedInteractionDialog::addButtonXY(uint x, uint y, uint w, uint h, const Common::String name, uint32 cmd) {
- _buttonArray.push_back(new GUI::ButtonWidget(this, x, _yOffset, w, h, name, cmd));
+ _buttonArray.push_back(new GUI::ButtonWidget(this, x, _yOffset, w, h, name, 0, cmd));
}
void TestbedInteractionDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data) {
diff --git a/engines/testbed/detection.cpp b/engines/testbed/detection.cpp
index 6267be7f06..bb633e9812 100644
--- a/engines/testbed/detection.cpp
+++ b/engines/testbed/detection.cpp
@@ -59,7 +59,9 @@ static const ADParams detectionParams = {
"testbed",
0,
ADGF_NO_FLAGS,
- Common::GUIO_NONE
+ Common::GUIO_NONE,
+ 1,
+ 0
};
class TestbedMetaEngine : public AdvancedMetaEngine {
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 60eb08a2dd..fdc4484a7c 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/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/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/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 4c3c770c60..06589d99b0 100644
--- a/graphics/video/avi_decoder.cpp
+++ b/graphics/video/avi_decoder.cpp
@@ -211,10 +211,10 @@ void AviDecoder::handleStreamHeader() {
}
}
-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
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
index d3448bb8f7..9892f9d966 100644
--- a/graphics/video/codecs/cinepak.cpp
+++ b/graphics/video/codecs/cinepak.cpp
@@ -53,8 +53,11 @@ CinepakDecoder::CinepakDecoder() : Codec() {
}
CinepakDecoder::~CinepakDecoder() {
- if (_curFrame.surface)
+ if (_curFrame.surface) {
_curFrame.surface->free();
+ delete _curFrame.surface;
+ }
+
delete[] _curFrame.strips;
}
diff --git a/graphics/video/codecs/qdm2.cpp b/graphics/video/codecs/qdm2.cpp
index e12be21303..9f151b4ba8 100644
--- a/graphics/video/codecs/qdm2.cpp
+++ b/graphics/video/codecs/qdm2.cpp
@@ -157,7 +157,7 @@ public:
~QDM2Stream();
bool isStereo() const { return _channels == 2; }
- bool endOfData() const { return ((_stream->pos() == _stream->size()) && (_outputSamples.size() == 0)); }
+ 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);
@@ -199,7 +199,7 @@ private:
int _fftCoefsMinIndex[5];
int _fftCoefsMaxIndex[5];
int _fftLevelExp[6];
- //RDFTContext _rdftCtx;
+ RDFTContext _rdftCtx;
QDM2FFT _fft;
// I/O data
@@ -230,6 +230,7 @@ private:
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];
@@ -261,8 +262,6 @@ private:
float _noiseSamples[128];
void initNoiseSamples(void);
- RDFTContext _rdftCtx;
-
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);
@@ -331,8 +330,6 @@ static inline int scummvm_log2(int n) {
static inline void initGetBits(GetBitContext *s, const uint8 *buffer, int bitSize) {
int bufferSize = (bitSize + 7) >> 3;
- debug(1, "void initGetBits(GetBitContext *s, const uint8 *buffer, int bitSize)");
-
if (bufferSize < 0 || bitSize < 0) {
bufferSize = bitSize = 0;
buffer = NULL;
@@ -345,7 +342,6 @@ static inline void initGetBits(GetBitContext *s, const uint8 *buffer, int bitSiz
}
static inline int getBitsCount(GetBitContext *s) {
- debug(1, "int getBitsCount(GetBitContext *s)");
return s->index;
}
@@ -353,13 +349,9 @@ static inline unsigned int getBits1(GetBitContext *s) {
int index;
uint8 result;
- debug(1, "unsigned int getBits1(GetBitContext *s)");
-
index = s->index;
result = s->buffer[index >> 3];
- debug(1, "index : %d", index);
-
result >>= (index & 0x07);
result &= 1;
index++;
@@ -371,12 +363,8 @@ static inline unsigned int getBits1(GetBitContext *s) {
static inline unsigned int getBits(GetBitContext *s, int n) {
int tmp, reCache, reIndex;
- debug(1, "unsigned int getBits(GetBitContext *s, int n)");
-
reIndex = s->index;
- debug(1, "reIndex : %d", reIndex);
-
reCache = READ_LE_UINT32((const uint8 *)s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
tmp = (reCache) & ((uint32)0xffffffff >> (32 - n));
@@ -389,13 +377,9 @@ static inline unsigned int getBits(GetBitContext *s, int n) {
static inline void skipBits(GetBitContext *s, int n) {
int reIndex, reCache;
- debug(1, "void skipBits(GetBitContext *s, int n)");
-
reIndex = s->index;
reCache = 0;
- debug(1, "reIndex : %d", reIndex);
-
reCache = READ_LE_UINT32((const uint8 *)s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
s->index = reIndex + n;
}
@@ -1331,20 +1315,12 @@ static int getVlc2(GetBitContext *s, int16 (*table)[2], int bits, int maxDepth)
int code;
int n;
- debug(1, "int getVlc2(GetBitContext *s, int16 (*table)[2], int bits, int maxDepth)");
-
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];
- debug(1, "reIndex : %d", reIndex);
- debug(1, "reCache : %d", reCache);
- debug(1, "index : %d", index);
- debug(1, "code : %d", code);
- debug(1, "n : %d", n);
-
if (maxDepth > 1 && n < 0){
reIndex += bits;
reCache = READ_LE_UINT32(s->buffer + (reIndex >> 3)) >> (reIndex & 0x07);
@@ -1416,7 +1392,6 @@ static int build_table(VLC *vlc, int table_nb_bits,
table_size = 1 << table_nb_bits;
table_index = allocTable(vlc, table_size, flags & 4);
- debug(2, "QDM2 new table index=%d size=%d code_prefix=%x n=%d", table_index, table_size, code_prefix, n_prefix);
if (table_index < 0)
return -1;
table = &vlc->table[table_index];
@@ -1437,7 +1412,6 @@ static int build_table(VLC *vlc, int table_nb_bits,
symbol = i;
else
GET_DATA(symbol, symbols, i, symbols_wrap, symbols_size);
- debug(2, "QDM2 i=%d n=%d code=0x%x", i, n, code);
// if code matches the prefix, it is in the table
n -= n_prefix;
if(flags & 2)
@@ -1452,7 +1426,6 @@ static int build_table(VLC *vlc, int table_nb_bits,
for(k = 0; k < nb; k++) {
if(flags & 2)
j = (code >> n_prefix) + (k<<n);
- debug(2, "QDM2 %4x: code=%d n=%d",j, i, n);
if (table[j][1] /*bits*/ != 0) {
error("QDM2 incorrect codes");
return -1;
@@ -1464,7 +1437,6 @@ static int build_table(VLC *vlc, int table_nb_bits,
} else {
n -= table_nb_bits;
j = (code >> ((flags & 2) ? n_prefix : n)) & ((1 << table_nb_bits) - 1);
- debug(2, "QDM2 %4x: n=%d (subtable)", j, n);
// compute table size
n1 = -table[j][1]; //bits
if (n > n1)
@@ -1537,8 +1509,6 @@ void initVlcSparse(VLC *vlc, int nb_bits, int nb_codes,
error("called on a partially initialized table");
}
- debug(2, "QDM2 build table nb_codes=%d", nb_codes);
-
if (build_table(vlc, nb_bits, nb_codes,
bits, bits_wrap, bits_size,
codes, codes_wrap, codes_size,
@@ -1754,6 +1724,7 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadS
_stream = stream;
_compressedData = NULL;
_subPacket = 0;
+ _superBlockStart = 0;
memset(_quantizedCoeffs, 0, sizeof(_quantizedCoeffs));
memset(_fftLevelExp, 0, sizeof(_fftLevelExp));
_noiseIdx = 0;
@@ -2015,8 +1986,6 @@ static void qdm2_decode_sub_packet_header(GetBitContext *gb, QDM2SubPacket *sub_
sub_packet->data = &gb->buffer[getBitsCount(gb) / 8]; // FIXME: this depends on bitreader internal data
}
-
- debug(1, "QDM2 Subpacket: type=%d size=%d start_offs=%x", sub_packet->type, sub_packet->size, getBitsCount(gb) / 8);
}
/**
@@ -2881,7 +2850,6 @@ void QDM2Stream::qdm2_fft_init_coefficient(int sub_packet, int offset, int durat
}
void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) {
- debug(1, "QDM2Stream::qdm2_fft_decode_tones() duration: %d b:%d", duration, 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;
@@ -2896,9 +2864,7 @@ void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) {
while (1) {
if (_superblocktype_2_3) {
- debug(1, "QDM2Stream::qdm2_fft_decode_tones() local_int_8: %d", local_int_8);
while ((n = qdm2_get_vlc(gb, &_vlcTabFftToneOffset[local_int_8], 1, 2)) < 2) {
- debug(1, "QDM2Stream::qdm2_fft_decode_tones() local_int_8: %d", local_int_8);
offset = 1;
if (n == 0) {
local_int_4 += local_int_10;
@@ -2959,7 +2925,6 @@ void QDM2Stream::qdm2_fft_decode_tones(int duration, GetBitContext *gb, int b) {
}
void QDM2Stream::qdm2_decode_fft_packets(void) {
- debug(1, "QDM2Stream::qdm2_decode_fft_packets()");
int i, j, min, max, value, type, unknown_flag;
GetBitContext gb;
@@ -2994,7 +2959,6 @@ void QDM2Stream::qdm2_decode_fft_packets(void) {
return;
// decode FFT tones
- debug(1, "QDM2Stream::qdm2_decode_fft_packets initGetBits() packet->size*8: %d", packet->size*8);
initGetBits(&gb, packet->data, packet->size*8);
if (packet->type >= 32 && packet->type < 48 && !fft_subpackets[packet->type - 16])
@@ -3008,19 +2972,16 @@ void QDM2Stream::qdm2_decode_fft_packets(void) {
int duration = _subSampling + 5 - (type & 15);
if (duration >= 0 && duration < 4) { // TODO: Should be <= 4?
- debug(1, "QDM2Stream::qdm2_decode_fft_packets qdm2_fft_decode_tones() #1");
qdm2_fft_decode_tones(duration, &gb, unknown_flag);
}
} else if (type == 31) {
for (j=0; j < 4; j++) {
- debug(1, "QDM2Stream::qdm2_decode_fft_packets qdm2_fft_decode_tones() #2");
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++) {
- debug(1, "QDM2Stream::qdm2_decode_fft_packets qdm2_fft_decode_tones() #3");
qdm2_fft_decode_tones(j, &gb, unknown_flag);
}
}
@@ -3151,16 +3112,12 @@ void QDM2Stream::qdm2_fft_tone_synthesizer(uint8 sub_packet) {
}
void QDM2Stream::qdm2_calculate_fft(int channel) {
- debug(1, "QDM2Stream::qdm2_calculate_fft channel: %d", 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;
- //debug(1, "QDM2Stream::qdm2_calculate_fft _fft.complex[channel][0].re: %lf", _fft.complex[channel][0].re);
- //debug(1, "QDM2Stream::qdm2_calculate_fft _fft.complex[channel][0].im: %lf", _fft.complex[channel][0].im);
-
rdftCalc(&_rdftCtx, (float *)_fft.complex[channel]);
// add samples to output buffer
@@ -3209,82 +3166,80 @@ int QDM2Stream::qdm2_decodeFrame(Common::SeekableReadStream *in) {
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->size() == in->pos()) {
+ if (in->eos() || in->pos() >= in->size()) {
debug(1, "QDM2Stream::qdm2_decodeFrame End of Input Stream");
return 0;
}
- if((in->size() - in->pos()) < _packetSize) {
+
+ 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;
}
- in->read(_compressedData, _packetSize);
- debug(1, "QDM2Stream::qdm2_decodeFrame constructed input data");
+ 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");
- // 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();
+ 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();
}
- 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);
+ // 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();
+ }
- if (!_hasErrors && _subPacketListC[0].packet != NULL) {
- error("QDM2 : has errors, and C list is not empty");
- return 0;
+ debug(1, "QDM2Stream::qdm2_decodeFrame qdm2_fft_tone_synthesizer(%d)", _subPacket);
+ qdm2_fft_tone_synthesizer(_subPacket);
}
- }
- // 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);
+ // 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);
- _subPacket = (_subPacket + 1) % 16;
+ if (!_hasErrors && _subPacketListC[0].packet != NULL) {
+ error("QDM2 : has errors, and C list is not empty");
+ return 0;
+ }
+ }
- if(_hasErrors)
- warning("QDM2 Packet error...");
+ // 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);
- // clip and convert output float[] to 16bit signed samples
- debug(1, "QDM2Stream::qdm2_decodeFrame clip and convert output float[] to 16bit signed samples");
+ _subPacket = (_subPacket + 1) % 16;
-/*
- debugN(1, "Input Data Packet:");
- for(i = 0; i < _packetSize; i++) {
- debugN(1, " %d", _compressedData[i]);
- }
- debugN(1, " Output Data Packet:");
- for(i = 0; i < frame_size; i++) {
- debugN(1, " %d", (int)_outputBuffer[i]);
+ 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");
}
- debug(1, "");
-*/
for (i = 0; i < frame_size; i++) {
- //debug(1, "QDM2Stream::qdm2_decodeFrame i: %d", i);
int value = (int)_outputBuffer[i];
if (value > SOFTCLIP_THRESHOLD)
@@ -3302,17 +3257,17 @@ int QDM2Stream::readBuffer(int16 *buffer, const int numSamples) {
int32 decodedSamples = _outputSamples.size();
int32 i;
- //while((int)_outputSamples.size() < numSamples) {
- while(!_stream->eos() && _stream->pos() != _stream->size()) {
+ while (decodedSamples < numSamples) {
i = qdm2_decodeFrame(_stream);
- if(i == 0)
+ if (i == 0)
break; // Out Of Decode Frames...
decodedSamples += i;
}
- if(decodedSamples > numSamples)
+
+ if (decodedSamples > numSamples)
decodedSamples = numSamples;
- for(i = 0; i < decodedSamples; i++)
+ for (i = 0; i < decodedSamples; i++)
buffer[i] = _outputSamples.remove_at(0);
return decodedSamples;
diff --git a/graphics/video/codecs/qdm2.h b/graphics/video/codecs/qdm2.h
index c9a01a70ee..9eb566d04d 100644
--- a/graphics/video/codecs/qdm2.h
+++ b/graphics/video/codecs/qdm2.h
@@ -44,7 +44,7 @@ namespace Graphics {
*
* @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 occured
+ * @return a new AudioStream, or NULL, if an error occurred
*/
Audio::AudioStream *makeQDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadStream *extraData);
diff --git a/graphics/video/coktelvideo/coktelvideo.cpp b/graphics/video/coktelvideo/coktelvideo.cpp
index 4d93815b44..9ee9fd68d0 100644
--- a/graphics/video/coktelvideo/coktelvideo.cpp
+++ b/graphics/video/coktelvideo/coktelvideo.cpp
@@ -127,14 +127,14 @@ Common::MemoryReadStream *PreImd::getExtraData(const char *fileName) {
return 0;
}
-bool PreImd::load(Common::SeekableReadStream &stream) {
+bool PreImd::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((_forcedWidth > 0) && (_forcedHeight > 0));
unload();
- _stream = &stream;
+ _stream = stream;
_stream->seek(0);
@@ -564,10 +564,10 @@ bool Imd::loadFrameTables(uint32 framesPosPos, uint32 framesCoordsPos) {
return true;
}
-bool Imd::load(Common::SeekableReadStream &stream) {
+bool Imd::load(Common::SeekableReadStream *stream) {
unload();
- _stream = &stream;
+ _stream = stream;
uint16 handle;
@@ -1656,10 +1656,10 @@ void Vmd::readExtraData() {
}
}
-bool Vmd::load(Common::SeekableReadStream &stream) {
+bool Vmd::load(Common::SeekableReadStream *stream) {
unload();
- _stream = &stream;
+ _stream = stream;
uint16 headerLength;
uint16 handle;
diff --git a/graphics/video/coktelvideo/coktelvideo.h b/graphics/video/coktelvideo/coktelvideo.h
index 8fbd861e82..f8b1965f41 100644
--- a/graphics/video/coktelvideo/coktelvideo.h
+++ b/graphics/video/coktelvideo/coktelvideo.h
@@ -23,12 +23,8 @@
*
*/
-// 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 CoktelVideo code
-
-#else
+// Currently, only GOB and SCI32 games play IMDs and VMDs
+#if defined(ENABLE_GOB) || defined(ENABLE_SCI32) || defined(DYNAMIC_MODULES)
#ifndef GRAPHICS_VIDEO_COKTELVIDEO_H
#define GRAPHICS_VIDEO_COKTELVIDEO_H
@@ -153,7 +149,7 @@ public:
virtual Common::MemoryReadStream *getExtraData(const char *fileName) = 0;
/** Load a video out of a stream. */
- virtual bool load(Common::SeekableReadStream &stream) = 0;
+ virtual bool load(Common::SeekableReadStream *stream) = 0;
/** Unload the currently loaded video. */
virtual void unload() = 0;
@@ -243,7 +239,7 @@ public:
bool hasExtraData(const char *fileName) const;
Common::MemoryReadStream *getExtraData(const char *fileName);
- bool load(Common::SeekableReadStream &stream);
+ bool load(Common::SeekableReadStream *stream);
void unload();
void setXY(int16 x, int16 y);
@@ -322,7 +318,7 @@ public:
uint32 getSyncLag() const;
- bool load(Common::SeekableReadStream &stream);
+ bool load(Common::SeekableReadStream *stream);
void unload();
void setXY(int16 x, int16 y);
@@ -451,7 +447,7 @@ public:
bool hasExtraData(const char *fileName) const;
Common::MemoryReadStream *getExtraData(const char *fileName);
- bool load(Common::SeekableReadStream &stream);
+ bool load(Common::SeekableReadStream *stream);
void unload();
int16 getWidth() const;
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.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
index 49d2b0aed9..470441dab8 100644
--- a/graphics/video/qt_decoder.cpp
+++ b/graphics/video/qt_decoder.cpp
@@ -191,8 +191,10 @@ Codec *QuickTimeDecoder::createCodec(uint32 codecTag, byte bitsPerPixel) {
}
void QuickTimeDecoder::startAudio() {
- if (_audStream) // No audio/audio not supported
+ if (_audStream) { // No audio/audio not supported
+ updateAudioBuffer();
g_system->getMixer()->playStream(Audio::Mixer::kPlainSoundType, &_audHandle, _audStream);
+ }
}
void QuickTimeDecoder::stopAudio() {
@@ -204,7 +206,7 @@ void QuickTimeDecoder::stopAudio() {
void QuickTimeDecoder::pauseVideoIntern(bool pause) {
if (_audStream)
- g_system->getMixer()->pauseHandle(_audHandle, pause);
+ g_system->getMixer()->pauseHandle(_audHandle, pause);
}
Surface *QuickTimeDecoder::decodeNextFrame() {
@@ -306,8 +308,8 @@ bool QuickTimeDecoder::loadFile(const Common::String &filename) {
return true;
}
-bool QuickTimeDecoder::load(Common::SeekableReadStream &stream) {
- _fd = &stream;
+bool QuickTimeDecoder::load(Common::SeekableReadStream *stream) {
+ _fd = stream;
_foundMOOV = _foundMDAT = false;
_numStreams = 0;
_partial = 0;
@@ -534,6 +536,8 @@ int QuickTimeDecoder::readCMOV(MOVatom atom) {
unsigned long dstLen = uncompressedSize;
if (!Common::uncompress(uncompressedData, &dstLen, compressedData, compressedSize)) {
warning ("Could not uncompress cmov chunk");
+ free(compressedData);
+ free(uncompressedData);
return -1;
}
diff --git a/graphics/video/qt_decoder.h b/graphics/video/qt_decoder.h
index db4ff8180b..196d4c02cb 100644
--- a/graphics/video/qt_decoder.h
+++ b/graphics/video/qt_decoder.h
@@ -89,7 +89,7 @@ public:
* Load a QuickTime video file from a SeekableReadStream
* @param stream the stream to load
*/
- bool load(Common::SeekableReadStream &stream);
+ bool load(Common::SeekableReadStream *stream);
/**
* Close a QuickTime encoded video file
diff --git a/graphics/video/smk_decoder.cpp b/graphics/video/smk_decoder.cpp
index 0b7de774eb..4d03305cce 100644
--- a/graphics/video/smk_decoder.cpp
+++ b/graphics/video/smk_decoder.cpp
@@ -367,10 +367,10 @@ uint32 SmackerDecoder::getElapsedTime() const {
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 97dde29824..4447b62244 100644
--- a/gui/ListWidget.cpp
+++ b/gui/ListWidget.cpp
@@ -36,8 +36,8 @@
namespace GUI {
-ListWidget::ListWidget(Dialog *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(Dialog *boss, const String &name, uint32 cmd)
_editColor = ThemeEngine::kFontColorNormal;
}
-ListWidget::ListWidget(Dialog *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;
}
diff --git a/gui/ListWidget.h b/gui/ListWidget.h
index a3fb825761..3858fa6de2 100644
--- a/gui/ListWidget.h
+++ b/gui/ListWidget.h
@@ -87,8 +87,8 @@ protected:
ThemeEngine::FontColor _editColor;
public:
- ListWidget(Dialog *boss, const String &name, uint32 cmd = 0);
- ListWidget(Dialog *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 8b2f470bf6..3caab084ca 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"
@@ -92,22 +93,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 0df894a642..bd4ecffc9b 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -213,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)",
@@ -286,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",
@@ -363,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",
@@ -479,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 058f08e233..755e34e380 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 0f484c5233..d50e7ce578 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
@@ -865,11 +890,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();
}
}
@@ -981,8 +1006,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);
@@ -1029,7 +1054,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 93897a7d88..46ac4a1365 100644
--- a/gui/themes/default.inc
+++ b/gui/themes/default.inc
@@ -1,397 +1,44 @@
"<?xml version = '1.0'?>"
-"<render_info> "
-"<palette> "
-"<color name='black' "
-"rgb='0,0,0' "
-"/> "
-"<color name='lightgrey' "
-"rgb='104,104,104' "
-"/> "
-"<color name='darkgrey' "
-"rgb='64,64,64' "
-"/> "
-"<color name='green' "
-"rgb='32,160,32' "
-"/> "
-"<color name='green2' "
-"rgb='0,255,0' "
-"/> "
-"</palette> "
-"<fonts> "
-"<font id='text_default' "
-"file='default' "
-"/> "
-"<font id='text_button' "
-"file='default' "
-"/> "
-"<font id='text_normal' "
-"file='default' "
-"/> "
-"<text_color id='color_normal' "
-"color='green' "
-"/> "
-"<text_color id='color_normal_inverted' "
-"color='black' "
-"/> "
-"<text_color id='color_normal_hover' "
-"color='green2' "
-"/> "
-"<text_color id='color_normal_disabled' "
-"color='lightgrey' "
-"/> "
-"<text_color id='color_alternative' "
-"color='lightgrey' "
-"/> "
-"<text_color id='color_alternative_inverted' "
-"color='255,255,255' "
-"/> "
-"<text_color id='color_alternative_hover' "
-"color='176,176,176' "
-"/> "
-"<text_color id='color_alternative_disabled' "
-"color='darkgrey' "
-"/> "
-"<text_color id='color_button' "
-"color='green' "
-"/> "
-"<text_color id='color_button_hover' "
-"color='green2' "
-"/> "
-"<text_color id='color_button_disabled' "
-"color='lightgrey' "
-"/> "
-"</fonts> "
-"<defaults fill='foreground' fg_color='darkgrey' bg_color='black' shadow='0' bevel_color='lightgrey'/> "
-"<drawdata id='text_selection' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='lightgrey' "
-"/> "
-"</drawdata> "
-"<drawdata id='text_selection_focus' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='green' "
-"/> "
-"</drawdata> "
-"<drawdata id='mainmenu_bg' cache='false'> "
-"<drawstep func='fill' "
-"fill='foreground' "
-"fg_color='black' "
-"/> "
-"</drawdata> "
-"<drawdata id='special_bg' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"/> "
-"</drawdata> "
-"<drawdata id='separator' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"height='2' "
-"ypos='center' "
-"fg_color='lightgrey' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_base' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_handle_hover' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='green2' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_handle_idle' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='green' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_button_idle' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"<drawstep func='triangle' "
-"fg_color='green' "
-"fill='foreground' "
-"width='auto' "
-"height='auto' "
-"xpos='center' "
-"ypos='center' "
-"orientation='top' "
-"/> "
-"</drawdata> "
-"<drawdata id='scrollbar_button_hover' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"<drawstep func='triangle' "
-"fg_color='green2' "
-"fill='foreground' "
-"width='auto' "
-"height='auto' "
-"xpos='center' "
-"ypos='center' "
-"orientation='top' "
-"/> "
-"</drawdata> "
-"<drawdata id='tab_active' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal_hover' "
-"vertical_align='center' "
-"horizontal_align='center' "
-"/> "
-"<drawstep func='tab' "
-"bevel='2' "
-"radius='0' "
-"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='tab_inactive' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal' "
-"vertical_align='center' "
-"horizontal_align='center' "
-"/> "
-"<drawstep func='tab' "
-"bevel='2' "
-"radius='0' "
-"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='tab_background' cache='false'> "
-"</drawdata> "
-"<drawdata id='widget_slider' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='slider_disabled' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='lightgrey' "
-"/> "
-"</drawdata> "
-"<drawdata id='slider_full' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='green' "
-"/> "
-"</drawdata> "
-"<drawdata id='slider_hover' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='green2' "
-"/> "
-"</drawdata> "
-"<drawdata id='widget_small' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='popup_idle' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"<drawstep func='triangle' "
-"fg_color='green' "
-"fill='foreground' "
-"width='height' "
-"height='auto' "
-"xpos='right' "
-"ypos='center' "
-"orientation='bottom' "
-"/> "
-"<text font='text_default' "
-"text_color='color_normal' "
-"vertical_align='center' "
-"horizontal_align='left' "
-"/> "
-"</drawdata> "
-"<drawdata id='popup_disabled' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"<drawstep func='triangle' "
-"fg_color='lightgrey' "
-"fill='foreground' "
-"width='height' "
-"height='auto' "
-"xpos='right' "
-"ypos='center' "
-"orientation='bottom' "
-"/> "
-"<text font='text_default' "
-"text_color='color_normal_disabled' "
-"vertical_align='center' "
-"horizontal_align='left' "
-"/> "
-"</drawdata> "
-"<drawdata id='popup_hover' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"<drawstep func='triangle' "
-"fg_color='green2' "
-"fill='foreground' "
-"width='height' "
-"height='auto' "
-"xpos='right' "
-"ypos='center' "
-"orientation='bottom' "
-"/> "
-"<text font='text_default' "
-"text_color='color_normal_hover' "
-"vertical_align='center' "
-"horizontal_align='left' "
-"/> "
-"</drawdata> "
-"<drawdata id='widget_textedit' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='plain_bg' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"/> "
-"</drawdata> "
-"<drawdata id='caret' cache='false'> "
-"<drawstep func='square' "
-"fill='foreground' "
-"fg_color='lightgrey' "
-"/> "
-"</drawdata> "
-"<drawdata id='default_bg' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"/> "
-"</drawdata> "
-"<drawdata id='button_idle' cache='false'> "
-"<text font='text_button' "
-"text_color='color_button' "
-"vertical_align='center' "
-"horizontal_align='center' "
-"/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='button_hover' cache='false'> "
-"<text font='text_button' "
-"text_color='color_button_hover' "
-"vertical_align='center' "
-"horizontal_align='center' "
-"/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='button_disabled' cache='false'> "
-"<text font='text_button' "
-"text_color='color_button_disabled' "
-"vertical_align='center' "
-"horizontal_align='center' "
-"/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='checkbox_disabled' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal_disabled' "
-"vertical_align='top' "
-"horizontal_align='left' "
-"/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='checkbox_selected' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal' "
-"vertical_align='top' "
-"horizontal_align='left' "
-"/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"<drawstep func='cross' "
-"fill='foreground' "
-"stroke='2' "
-"fg_color='green' "
-"/> "
-"</drawdata> "
-"<drawdata id='checkbox_default' cache='false'> "
-"<text font='text_default' "
-"text_color='color_normal' "
-"vertical_align='top' "
-"horizontal_align='left' "
-"/> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"fill='none' "
-"/> "
-"</drawdata> "
-"<drawdata id='widget_default' cache='false'> "
-"<drawstep func='bevelsq' "
-"bevel='2' "
-"/> "
-"</drawdata> "
-"</render_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' /> "
-"<def var='About.OuterBorder' value='80'/> "
-"<def var='Layout.Spacing' value='8' /> "
+"<def var='Line.Height' value='12' /> "
+"<def var='Font.Height' value='10' /> "
+"<def var='About.OuterBorder' value='10'/> "
+"<def var='Layout.Spacing' value='8'/> "
"<def var='ShowLauncherLogo' value='0'/> "
"<def var='ShowGlobalMenuLogo' value='0'/> "
"<def var='ShowSearchPic' value='0'/> "
-"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> "
-"<def var='KeyMapper.Spacing' value='10'/> "
-"<def var='KeyMapper.LabelWidth' value='100'/> "
-"<def var='KeyMapper.ButtonWidth' value='80'/> "
+"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> "
+"<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' "
+"/> "
+"<widget name='Slider' "
+"size='85,12' "
+"/> "
"<widget name='OptionsLabel' "
"size='110,Globals.Line.Height' "
"textalign='right' "
"/> "
"<widget name='SmallLabel' "
-"size='24,Globals.Line.Height' "
-"/> "
-"<widget name='ShortOptionsLabel' "
-"size='60,Globals.Line.Height' "
-"/> "
-"<widget name='Button' "
-"size='108,24' "
-"/> "
-"<widget name='Slider' "
-"size='128,18' "
+"size='18,Globals.Line.Height' "
"/> "
"<widget name='PopUp' "
-"size='-1,19' "
+"size='-1,15' "
"/> "
"<widget name='Checkbox' "
-"size='-1,14' "
+"size='-1,Globals.Line.Height' "
+"/> "
+"<widget name='Radiobutton' "
+"size='-1,Globals.Line.Height' "
"/> "
"<widget name='ListWidget' "
-"padding='5,0,8,0' "
+"padding='5,0,0,0' "
"/> "
"<widget name='PopUpWidget' "
"padding='7,5,0,0' "
@@ -403,25 +50,28 @@
"padding='7,5,5,5' "
"/> "
"<widget name='Scrollbar' "
-"size='15,0' "
+"size='9,0' "
"/> "
"<widget name='TabWidget.Tab' "
-"size='75,27' "
-"padding='0,0,8,0' "
+"size='45,16' "
+"padding='0,0,2,0' "
+"/> "
+"<widget name='TabWidget.Body' "
+"padding='0,0,0,-8' "
"/> "
"<widget name='TabWidget.NavButton' "
-"size='15,18' "
-"padding='0,3,4,0' "
+"size='32,18' "
+"padding='0,0,1,0' "
"/> "
"</globals> "
"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='16,16,8,8'> "
+"<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='60' "
+"width='50' "
"height='Globals.Line.Height' "
"textalign='right' "
"/> "
@@ -436,39 +86,38 @@
"<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='20' "
+"height='12' "
"/> "
"<widget name='AddGameButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='EditGameButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='RemoveGameButton' "
-"height='20' "
+"height='12' "
"/> "
"</layout> "
-"<space size='4'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='QuitButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='AboutButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='OptionsButton' "
-"height='20' "
+"height='12' "
"/> "
"<widget name='StartButton' "
-"height='20' "
+"height='12' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> "
+"<layout type='vertical' padding='8,8,0,4'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
"/> "
@@ -476,7 +125,7 @@
"height='Globals.Line.Height' "
"/> "
"<widget name='List'/> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"<layout type='horizontal' padding='0,0,8,0'> "
"<widget name='Up' "
"type='Button' "
"/> "
@@ -490,10 +139,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -506,7 +155,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Graphics' 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'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='grModePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -514,7 +163,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='grRenderPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -532,7 +181,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Audio' 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'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auMidiPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -540,7 +189,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auOPLPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -548,7 +197,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='auSampleRatePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -556,16 +205,21 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='3' center='true'> "
"<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'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -579,9 +233,8 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_Volume' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='horizontal' padding='16,16,16,16' spacing='8'> "
-"<layout type='vertical' padding='0,0,0,0' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -592,7 +245,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -603,7 +256,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -614,8 +267,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"</layout> "
-"<layout type='vertical' padding='24,0,24,0' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<space size='110' /> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
"/> "
@@ -624,7 +277,15 @@
"</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='10' center='true'> "
+"<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' "
"/> "
@@ -639,13 +300,7 @@
"<widget name='mcMixedCheckbox' "
"type='Checkbox' "
"/> "
-"<widget name='mcMt32Checkbox' "
-"type='Checkbox' "
-"/> "
-"<widget name='mcGSCheckbox' "
-"type='Checkbox' "
-"/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='mcMidiGainText' "
"type='OptionsLabel' "
"/> "
@@ -659,9 +314,27 @@
"</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='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='SaveButton' "
"type='Button' "
"/> "
@@ -669,7 +342,7 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -677,7 +350,7 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ExtraButton' "
"type='Button' "
"/> "
@@ -697,7 +370,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Misc' 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'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -705,22 +378,36 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='RendererPopupDesc' "
-"type='OptionsLabel' "
+"width='80' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='RendererPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='AutosavePeriodPopupDesc' "
-"type='OptionsLabel' "
+"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' "
"/> "
@@ -750,10 +437,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='16,16,16,4'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -765,7 +452,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -773,7 +460,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -781,15 +468,23 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
"<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='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -797,34 +492,43 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='Id' "
-"type='OptionsLabel' "
+"width='35' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='Domain' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='Name' "
-"type='OptionsLabel' "
+"width='35' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='Desc' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<space size='8'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='LangPopupDesc' "
-"type='OptionsLabel' "
+"width='60' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='LangPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='PlatformPopupDesc' "
-"type='OptionsLabel' "
+"width='60' "
+"height='Globals.Line.Height' "
+"textalign='right' "
"/> "
"<widget name='PlatformPopup' "
"type='PopUp' "
@@ -833,8 +537,8 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='16,16,16,16'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Savepath' "
"type='Button' "
"/> "
@@ -842,7 +546,7 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Extrapath' "
"type='Button' "
"/> "
@@ -850,7 +554,7 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
"<widget name='Gamepath' "
"type='Button' "
"/> "
@@ -861,57 +565,55 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='16,16,16,16' center='true'> "
+"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
"<widget name='Title' "
-"width='210' "
-"height='Globals.Line.Height' "
+"width='160' "
+"height='4' "
"/> "
"<widget name='Version' "
-"width='210' "
-"height='Globals.Line.Height' "
-"/> "
-"<widget name='Resume' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='160' "
+"height='4' "
"/> "
-"<space size='10'/> "
+"<space size='1'/> "
"<widget name='Load' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Save' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
-"<space size='10'/> "
+"<space size='1'/> "
"<widget name='Options' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Help' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='About' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
+"/> "
+"<space size='1'/> "
+"<widget name='Resume' "
+"width='120' "
+"height='12' "
"/> "
-"<space size='10'/> "
"<widget name='RTL' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"<widget name='Quit' "
-"width='150' "
-"height='Globals.Button.Height' "
+"width='120' "
+"height='12' "
"/> "
"</layout> "
"</dialog> "
"<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'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -922,7 +624,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -933,7 +635,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -944,25 +646,34 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"</layout> "
-"<layout type='vertical' padding='24,24,24,24' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<space size='110' /> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"width='80' "
+"width='80' "
"/> "
"</layout> "
-"</layout> "
-"<space size='8' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='1' center='true'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
-"<widget name='subToggleButton' "
-"width='158' "
-"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 type='horizontal' padding='0,0,0,0' spacing='10'> "
+"</layout> "
+"<space size='2' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -973,8 +684,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<space size='60'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<space size='16'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
"<widget name='Keys' "
"type='Button' "
"/> "
@@ -989,23 +700,15 @@
"</layout> "
"</dialog> "
"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,32' center='true'> "
-"<widget name='Title' "
-"height='Globals.Line.Height' "
-"/> "
-"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<widget name='Title' height='Globals.Line.Height'/> "
"<widget name='List' /> "
-"<widget name='Thumbnail' "
-"width='180' "
-"height='200' "
-"/> "
-"</layout> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,16,0'> "
"<space/> "
"<widget name='Delete' "
"type='Button' "
"/> "
-"<space size='32'/> "
+"<space size='16'/> "
"<widget name='Cancel' "
"type='Button' "
"/> "
@@ -1015,16 +718,16 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='ScummHelp' overlays='screen_center'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
+"<dialog name='ScummHelp' overlays='screen'> "
+"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='Title' "
-"width='320' "
+"width='180' "
"height='Globals.Line.Height' "
"/> "
"<widget name='HelpText' "
-"height='200' "
+"height='140' "
"/> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='Prev' "
"type='Button' "
"/> "
@@ -1039,20 +742,20 @@
"</layout> "
"</dialog> "
"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' center='true'> "
+"<layout type='vertical' padding='4,4,16,4' center='true'> "
"<widget name='DirProgressText' "
-"width='480' "
+"width='280' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameProgressText' "
-"width='480' "
+"width='280' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameList' "
-"width='480' "
-"height='250' "
+"width='280' "
+"height='100' "
"/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='4,4,4,4'> "
"<widget name='Ok' "
"type='Button' "
"/> "
@@ -1063,20 +766,20 @@
"</layout> "
"</dialog> "
"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PopupDesc' "
"type='OptionsLabel' "
"/> "
"<widget name='Popup' "
"type='PopUp' "
-"width='400' "
+"width='150' "
"height='Globals.Line.Height' "
"/> "
"</layout> "
"<widget name='KeymapArea' "
-"width='600' "
-"height='280' "
+"width='300' "
+"height='120' "
"/> "
"<widget name='Close' "
"type='Button' "
@@ -1084,40 +787,49 @@
"</layout> "
"</dialog> "
"</layout_info> "
-"<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' /> "
-"<def var='About.OuterBorder' value='10'/> "
-"<def var='Layout.Spacing' value='8'/> "
+"<def var='Line.Height' value='16' /> "
+"<def var='Font.Height' value='16' /> "
+"<def var='About.OuterBorder' value='80'/> "
+"<def var='Layout.Spacing' value='8' /> "
"<def var='ShowLauncherLogo' value='0'/> "
"<def var='ShowGlobalMenuLogo' value='0'/> "
"<def var='ShowSearchPic' value='0'/> "
-"<def var='SaveLoadChooser.ExtInfo.Visible' value='0'/> "
-"<def var='KeyMapper.Spacing' value='5'/> "
-"<def var='KeyMapper.LabelWidth' value='80'/> "
-"<def var='KeyMapper.ButtonWidth' value='60'/> "
-"<widget name='Button' "
-"size='72,16' "
-"/> "
-"<widget name='Slider' "
-"size='85,12' "
-"/> "
+"<def var='SaveLoadChooser.ExtInfo.Visible' value='1'/> "
+"<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' "
"/> "
"<widget name='SmallLabel' "
-"size='18,Globals.Line.Height' "
+"size='24,Globals.Line.Height' "
+"/> "
+"<widget name='ShortOptionsLabel' "
+"size='60,Globals.Line.Height' "
+"/> "
+"<widget name='Button' "
+"size='108,24' "
+"/> "
+"<widget name='Slider' "
+"size='128,18' "
"/> "
"<widget name='PopUp' "
-"size='-1,15' "
+"size='-1,19' "
"/> "
"<widget name='Checkbox' "
+"size='-1,14' "
+"/> "
+"<widget name='Radiobutton' "
"size='-1,Globals.Line.Height' "
"/> "
"<widget name='ListWidget' "
-"padding='5,0,0,0' "
+"padding='5,0,8,0' "
"/> "
"<widget name='PopUpWidget' "
"padding='7,5,0,0' "
@@ -1129,25 +841,28 @@
"padding='7,5,5,5' "
"/> "
"<widget name='Scrollbar' "
-"size='9,0' "
+"size='15,0' "
"/> "
"<widget name='TabWidget.Tab' "
-"size='45,16' "
-"padding='0,0,2,0' "
+"size='75,27' "
+"padding='0,0,8,0' "
+"/> "
+"<widget name='TabWidget.Body' "
+"padding='0,0,0,0' "
"/> "
"<widget name='TabWidget.NavButton' "
-"size='32,18' "
+"size='15,18' "
"padding='0,3,4,0' "
"/> "
"</globals> "
"<dialog name='Launcher' overlays='screen'> "
-"<layout type='vertical' center='true' padding='8,8,4,4'> "
+"<layout type='vertical' center='true' padding='16,16,8,8'> "
"<widget name='Version' "
"height='Globals.Line.Height' "
"/> "
"<layout type='horizontal' spacing='5' padding='10,0,0,0'> "
"<widget name='SearchDesc' "
-"width='50' "
+"width='60' "
"height='Globals.Line.Height' "
"textalign='right' "
"/> "
@@ -1164,36 +879,37 @@
"<widget name='GameList'/> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='LoadGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='AddGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='EditGameButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='RemoveGameButton' "
-"height='12' "
+"height='20' "
"/> "
"</layout> "
+"<space size='4'/> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='QuitButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='AboutButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='OptionsButton' "
-"height='12' "
+"height='20' "
"/> "
"<widget name='StartButton' "
-"height='12' "
+"height='20' "
"/> "
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='Browser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,0,4'> "
+"<dialog name='Browser' overlays='Dialog.Launcher.GameList' shading='dim'> "
+"<layout type='vertical' padding='8,8,8,8'> "
"<widget name='Headline' "
"height='Globals.Line.Height' "
"/> "
@@ -1201,7 +917,7 @@
"height='Globals.Line.Height' "
"/> "
"<widget name='List'/> "
-"<layout type='horizontal' padding='0,0,8,0'> "
+"<layout type='horizontal' padding='0,0,16,0'> "
"<widget name='Up' "
"type='Button' "
"/> "
@@ -1215,10 +931,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GlobalOptions' overlays='screen' inset='16' shading='dim'> "
+"<dialog name='GlobalOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='16,16,16,16'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -1231,7 +947,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Graphics' 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'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='grModePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1239,7 +955,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='grRenderPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1257,7 +973,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Audio' 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'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auMidiPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1265,7 +981,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auOPLPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1273,7 +989,7 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='auSampleRatePopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1281,16 +997,21 @@
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<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'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -1304,8 +1025,9 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalOptions_Volume' 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'> "
+"<layout type='horizontal' padding='16,16,16,16' spacing='8'> "
+"<layout type='vertical' padding='0,0,0,0' spacing='8'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -1316,7 +1038,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -1327,7 +1049,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -1338,8 +1060,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
+"</layout> "
+"<layout type='vertical' padding='24,0,24,0' center='true'> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
"/> "
@@ -1348,7 +1070,15 @@
"</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='16' center='true'> "
+"<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' "
"/> "
@@ -1363,13 +1093,7 @@
"<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'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<widget name='mcMidiGainText' "
"type='OptionsLabel' "
"/> "
@@ -1383,9 +1107,27 @@
"</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='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='SaveButton' "
"type='Button' "
"/> "
@@ -1393,7 +1135,7 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -1401,7 +1143,7 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ExtraButton' "
"type='Button' "
"/> "
@@ -1421,7 +1163,7 @@
"</dialog> "
"<dialog name='GlobalOptions_Misc' overlays='Dialog.GlobalOptions.TabWidget'> "
"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='ThemeButton' "
"type='Button' "
"/> "
@@ -1429,26 +1171,30 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='RendererPopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='RendererPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='AutosavePeriodPopupDesc' "
-"width='80' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='AutosavePeriodPopup' "
"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' "
"/> "
@@ -1478,10 +1224,10 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='GameOptions' overlays='screen' inset='16' shading='dim'> "
+"<dialog name='GameOptions' overlays='Dialog.Launcher.GameList' shading='dim'> "
"<layout type='vertical' padding='0,0,0,0' spacing='16'> "
"<widget name='TabWidget'/> "
-"<layout type='horizontal' padding='8,8,8,8'> "
+"<layout type='horizontal' padding='16,16,16,4'> "
"<space/> "
"<widget name='Cancel' "
"type='Button' "
@@ -1493,7 +1239,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Graphics' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1501,7 +1247,7 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Audio' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1509,15 +1255,23 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_MIDI' overlays='Dialog.GlobalOptions.TabWidget'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
"<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='8,8,8,8' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' spacing='8'> "
"<widget name='EnableTabCheckbox' "
"type='Checkbox' "
"/> "
@@ -1525,43 +1279,34 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Game' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Id' "
-"width='35' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='Domain' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Name' "
-"width='35' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='Desc' "
"type='PopUp' "
"/> "
"</layout> "
-"<space size='8'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='LangPopupDesc' "
-"width='60' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='LangPopup' "
"type='PopUp' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PlatformPopupDesc' "
-"width='60' "
-"height='Globals.Line.Height' "
-"textalign='right' "
+"type='OptionsLabel' "
"/> "
"<widget name='PlatformPopup' "
"type='PopUp' "
@@ -1570,8 +1315,8 @@
"</layout> "
"</dialog> "
"<dialog name='GameOptions_Paths' overlays='Dialog.GameOptions.TabWidget' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8'> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='vertical' padding='16,16,16,16'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Savepath' "
"type='Button' "
"/> "
@@ -1579,7 +1324,7 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Extrapath' "
"type='Button' "
"/> "
@@ -1587,7 +1332,7 @@
"height='Globals.Line.Height' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='16' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='Gamepath' "
"type='Button' "
"/> "
@@ -1598,55 +1343,57 @@
"</layout> "
"</dialog> "
"<dialog name='GlobalMenu' overlays='screen_center'> "
-"<layout type='vertical' padding='2,2,4,6' center='true' spacing='6'> "
+"<layout type='vertical' padding='16,16,16,16' center='true'> "
"<widget name='Title' "
-"width='160' "
-"height='4' "
+"width='210' "
+"height='Globals.Line.Height' "
"/> "
"<widget name='Version' "
-"width='160' "
-"height='4' "
+"width='210' "
+"height='Globals.Line.Height' "
"/> "
-"<space size='1'/> "
+"<widget name='Resume' "
+"width='150' "
+"height='Globals.Button.Height' "
+"/> "
+"<space size='10'/> "
"<widget name='Load' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Save' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
-"<space size='1'/> "
+"<space size='10'/> "
"<widget name='Options' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Help' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='About' "
-"width='120' "
-"height='12' "
-"/> "
-"<space size='1'/> "
-"<widget name='Resume' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
+"<space size='10'/> "
"<widget name='RTL' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"<widget name='Quit' "
-"width='120' "
-"height='12' "
+"width='150' "
+"height='Globals.Button.Height' "
"/> "
"</layout> "
"</dialog> "
"<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'> "
+"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='vertical' padding='0,0,0,0' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcMusicText' "
"type='OptionsLabel' "
"/> "
@@ -1657,7 +1404,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcSfxText' "
"type='OptionsLabel' "
"/> "
@@ -1668,7 +1415,7 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='8'> "
"<widget name='vcSpeechText' "
"type='OptionsLabel' "
"/> "
@@ -1679,24 +1426,33 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
-"<space size='110' /> "
+"</layout> "
+"<layout type='vertical' padding='24,24,24,24' center='true'> "
"<widget name='vcMuteCheckbox' "
"type='Checkbox' "
-"width='80' "
+"width='80' "
"/> "
"</layout> "
-"<space size='4' /> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
+"</layout> "
+"<space size='8' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subToggleDesc' "
"type='OptionsLabel' "
"/> "
-"<widget name='subToggleButton' "
-"width='128' "
-"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='6' center='true'> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -1707,8 +1463,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<space size='20'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
+"<space size='60'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
"<widget name='Keys' "
"type='Button' "
"/> "
@@ -1723,15 +1479,23 @@
"</layout> "
"</dialog> "
"<dialog name='SaveLoadChooser' overlays='screen' inset='8' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' center='true'> "
-"<widget name='Title' height='Globals.Line.Height'/> "
+"<layout type='vertical' padding='8,8,8,32' center='true'> "
+"<widget name='Title' "
+"height='Globals.Line.Height' "
+"/> "
+"<layout type='horizontal' padding='0,0,0,16' spacing='16'> "
"<widget name='List' /> "
-"<layout type='horizontal' padding='0,0,16,0'> "
+"<widget name='Thumbnail' "
+"width='180' "
+"height='200' "
+"/> "
+"</layout> "
+"<layout type='horizontal' padding='0,0,0,0'> "
"<space/> "
"<widget name='Delete' "
"type='Button' "
"/> "
-"<space size='16'/> "
+"<space size='32'/> "
"<widget name='Cancel' "
"type='Button' "
"/> "
@@ -1741,16 +1505,16 @@
"</layout> "
"</layout> "
"</dialog> "
-"<dialog name='ScummHelp' overlays='screen'> "
-"<layout type='vertical' padding='8,8,8,8'> "
+"<dialog name='ScummHelp' overlays='screen_center'> "
+"<layout type='vertical' padding='8,8,8,8' center='true'> "
"<widget name='Title' "
-"width='180' "
+"width='320' "
"height='Globals.Line.Height' "
"/> "
"<widget name='HelpText' "
-"height='140' "
+"height='200' "
"/> "
-"<layout type='horizontal' padding='0,0,0,0'> "
+"<layout type='horizontal' padding='0,0,16,0'> "
"<widget name='Prev' "
"type='Button' "
"/> "
@@ -1765,20 +1529,20 @@
"</layout> "
"</dialog> "
"<dialog name='MassAdd' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='4,4,16,4' center='true'> "
+"<layout type='vertical' padding='8,8,32,8' center='true'> "
"<widget name='DirProgressText' "
-"width='280' "
+"width='480' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameProgressText' "
-"width='280' "
+"width='480' "
"height='Globals.Line.Height' "
"/> "
"<widget name='GameList' "
-"width='280' "
-"height='100' "
+"width='480' "
+"height='250' "
"/> "
-"<layout type='horizontal' padding='4,4,4,4'> "
+"<layout type='horizontal' padding='8,8,8,8'> "
"<widget name='Ok' "
"type='Button' "
"/> "
@@ -1789,20 +1553,20 @@
"</layout> "
"</dialog> "
"<dialog name='KeyMapper' overlays='screen_center' shading='dim'> "
-"<layout type='vertical' padding='8,8,8,8' spacing='10' center='true'> "
+"<layout type='vertical' padding='8,8,32,8' spacing='10' center='true'> "
"<layout type='horizontal' padding='0,0,0,0' spacing='10' center='true'> "
"<widget name='PopupDesc' "
"type='OptionsLabel' "
"/> "
"<widget name='Popup' "
"type='PopUp' "
-"width='150' "
+"width='400' "
"height='Globals.Line.Height' "
"/> "
"</layout> "
"<widget name='KeymapArea' "
-"width='300' "
-"height='120' "
+"width='600' "
+"height='280' "
"/> "
"<widget name='Close' "
"type='Button' "
@@ -1810,3 +1574,443 @@
"</layout> "
"</dialog> "
"</layout_info> "
+"<render_info> "
+"<palette> "
+"<color name='black' "
+"rgb='0,0,0' "
+"/> "
+"<color name='lightgrey' "
+"rgb='104,104,104' "
+"/> "
+"<color name='darkgrey' "
+"rgb='64,64,64' "
+"/> "
+"<color name='green' "
+"rgb='32,160,32' "
+"/> "
+"<color name='green2' "
+"rgb='0,255,0' "
+"/> "
+"</palette> "
+"<fonts> "
+"<font id='text_default' "
+"file='helvb12.bdf' "
+"/> "
+"<font resolution='320xY,256x240' "
+"id='text_default' "
+"file='clR6x12.bdf' "
+"/> "
+"<font id='text_button' "
+"file='helvb12.bdf' "
+"/> "
+"<font resolution='320xY,256x240' "
+"id='text_button' "
+"file='clR6x12.bdf' "
+"/> "
+"<font id='text_normal' "
+"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' "
+"/> "
+"<text_color id='color_normal_inverted' "
+"color='black' "
+"/> "
+"<text_color id='color_normal_hover' "
+"color='green2' "
+"/> "
+"<text_color id='color_normal_disabled' "
+"color='lightgrey' "
+"/> "
+"<text_color id='color_alternative' "
+"color='lightgrey' "
+"/> "
+"<text_color id='color_alternative_inverted' "
+"color='255,255,255' "
+"/> "
+"<text_color id='color_alternative_hover' "
+"color='176,176,176' "
+"/> "
+"<text_color id='color_alternative_disabled' "
+"color='darkgrey' "
+"/> "
+"<text_color id='color_button' "
+"color='green' "
+"/> "
+"<text_color id='color_button_hover' "
+"color='green2' "
+"/> "
+"<text_color id='color_button_disabled' "
+"color='lightgrey' "
+"/> "
+"</fonts> "
+"<defaults fill='foreground' fg_color='darkgrey' bg_color='black' shadow='0' bevel_color='lightgrey'/> "
+"<drawdata id='text_selection' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='lightgrey' "
+"/> "
+"</drawdata> "
+"<drawdata id='text_selection_focus' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green' "
+"/> "
+"</drawdata> "
+"<drawdata id='mainmenu_bg' cache='false'> "
+"<drawstep func='fill' "
+"fill='foreground' "
+"fg_color='black' "
+"/> "
+"</drawdata> "
+"<drawdata id='special_bg' cache='false'> "
+"<drawstep func='bevelsq' "
+"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' "
+"height='2' "
+"ypos='center' "
+"fg_color='lightgrey' "
+"/> "
+"</drawdata> "
+"<drawdata id='scrollbar_base' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"/> "
+"</drawdata> "
+"<drawdata id='scrollbar_handle_hover' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green2' "
+"/> "
+"</drawdata> "
+"<drawdata id='scrollbar_handle_idle' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green' "
+"/> "
+"</drawdata> "
+"<drawdata id='scrollbar_button_idle' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"<drawstep func='triangle' "
+"fg_color='green' "
+"fill='foreground' "
+"width='auto' "
+"height='auto' "
+"xpos='center' "
+"ypos='center' "
+"orientation='top' "
+"/> "
+"</drawdata> "
+"<drawdata id='scrollbar_button_hover' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"<drawstep func='triangle' "
+"fg_color='green2' "
+"fill='foreground' "
+"width='auto' "
+"height='auto' "
+"xpos='center' "
+"ypos='center' "
+"orientation='top' "
+"/> "
+"</drawdata> "
+"<drawdata id='tab_active' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal_hover' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/> "
+"<drawstep func='tab' "
+"bevel='2' "
+"radius='0' "
+"fill='none' "
+"/> "
+"</drawdata> "
+"<drawdata id='tab_inactive' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/> "
+"<drawstep func='tab' "
+"bevel='2' "
+"radius='0' "
+"fill='none' "
+"/> "
+"</drawdata> "
+"<drawdata id='tab_background' cache='false'> "
+"</drawdata> "
+"<drawdata id='widget_slider' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"</drawdata> "
+"<drawdata id='slider_disabled' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='lightgrey' "
+"/> "
+"</drawdata> "
+"<drawdata id='slider_full' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green' "
+"/> "
+"</drawdata> "
+"<drawdata id='slider_hover' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='green2' "
+"/> "
+"</drawdata> "
+"<drawdata id='widget_small' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"</drawdata> "
+"<drawdata id='popup_idle' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"<drawstep func='triangle' "
+"fg_color='green' "
+"fill='foreground' "
+"width='height' "
+"height='auto' "
+"xpos='right' "
+"ypos='center' "
+"orientation='bottom' "
+"/> "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='center' "
+"horizontal_align='left' "
+"/> "
+"</drawdata> "
+"<drawdata id='popup_disabled' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"<drawstep func='triangle' "
+"fg_color='lightgrey' "
+"fill='foreground' "
+"width='height' "
+"height='auto' "
+"xpos='right' "
+"ypos='center' "
+"orientation='bottom' "
+"/> "
+"<text font='text_default' "
+"text_color='color_normal_disabled' "
+"vertical_align='center' "
+"horizontal_align='left' "
+"/> "
+"</drawdata> "
+"<drawdata id='popup_hover' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"<drawstep func='triangle' "
+"fg_color='green2' "
+"fill='foreground' "
+"width='height' "
+"height='auto' "
+"xpos='right' "
+"ypos='center' "
+"orientation='bottom' "
+"/> "
+"<text font='text_default' "
+"text_color='color_normal_hover' "
+"vertical_align='center' "
+"horizontal_align='left' "
+"/> "
+"</drawdata> "
+"<drawdata id='widget_textedit' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"</drawdata> "
+"<drawdata id='plain_bg' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"/> "
+"</drawdata> "
+"<drawdata id='caret' cache='false'> "
+"<drawstep func='square' "
+"fill='foreground' "
+"fg_color='lightgrey' "
+"/> "
+"</drawdata> "
+"<drawdata id='default_bg' cache='false'> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"/> "
+"</drawdata> "
+"<drawdata id='button_idle' cache='false'> "
+"<text font='text_button' "
+"text_color='color_button' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"</drawdata> "
+"<drawdata id='button_hover' cache='false'> "
+"<text font='text_button' "
+"text_color='color_button_hover' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"</drawdata> "
+"<drawdata id='button_disabled' cache='false'> "
+"<text font='text_button' "
+"text_color='color_button_disabled' "
+"vertical_align='center' "
+"horizontal_align='center' "
+"/> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"</drawdata> "
+"<drawdata id='checkbox_disabled' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal_disabled' "
+"vertical_align='top' "
+"horizontal_align='left' "
+"/> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"</drawdata> "
+"<drawdata id='checkbox_selected' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='top' "
+"horizontal_align='left' "
+"/> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"fill='none' "
+"/> "
+"<drawstep func='cross' "
+"fill='foreground' "
+"stroke='2' "
+"fg_color='green' "
+"/> "
+"</drawdata> "
+"<drawdata id='checkbox_default' cache='false'> "
+"<text font='text_default' "
+"text_color='color_normal' "
+"vertical_align='top' "
+"horizontal_align='left' "
+"/> "
+"<drawstep func='bevelsq' "
+"bevel='2' "
+"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 67cbbf7990..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 14f19a7151..74b8bf4b2c 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'
@@ -653,9 +706,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 8a0180db3c..65083f4bce 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'
@@ -654,16 +709,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'
@@ -675,7 +740,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 b3dc16b67e..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 25add37462..484dd15429 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'
@@ -666,9 +721,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 1c2f83a3b7..5998c50b60 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'
@@ -651,15 +708,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..07cf4407a2 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),
- _cmd(cmd), _hotkey(hotkey) {
+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) {
+
+ 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 8f51ebb005..0a7f6c4d92 100644
--- a/ports.mk
+++ b/ports.mk
@@ -65,8 +65,9 @@ endif
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)
@@ -101,6 +102,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.
@@ -109,6 +114,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/backends/fs/palmos/palmos-fs-factory.h b/sound/decoders/mac_snd.h
index 72729c570d..198a61333e 100644
--- a/backends/fs/palmos/palmos-fs-factory.h
+++ b/sound/decoders/mac_snd.h
@@ -8,42 +8,51 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You should have received a copy of the GNU General Public License
* along 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 PALMOS_FILESYSTEM_FACTORY_H
-#define PALMOS_FILESYSTEM_FACTORY_H
+#ifndef SOUND_MAC_SND_H
+#define SOUND_MAC_SND_H
+
+#include "common/scummsys.h"
+#include "common/types.h"
-#include "common/singleton.h"
-#include "backends/fs/fs-factory.h"
+namespace Common { class SeekableReadStream; }
+
+namespace Audio {
+
+class SeekableAudioStream;
/**
- * Creates PalmOSFilesystemNode objects.
+ * Try to load a Mac snd resource from the given seekable stream and create a SeekableAudioStream
+ * from that data.
*
- * Parts of this class are documented in the base interface class, FilesystemFactory.
+ * @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
*/
-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() {};
+SeekableAudioStream *makeMacSndStream(
+ Common::SeekableReadStream *stream,
+ DisposeAfterUse::Flag disposeAfterUse);
-private:
- friend class Common::Singleton<SingletonBaseType>;
-};
+} // End of namespace Audio
-#endif /*PALMOS_FILESYSTEM_FACTORY_H*/
+#endif
diff --git a/sound/decoders/mp3.cpp b/sound/decoders/mp3.cpp
index 732ae58b67..f22eae5102 100644
--- a/sound/decoders/mp3.cpp
+++ b/sound/decoders/mp3.cpp
@@ -349,13 +349,13 @@ 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
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 64869d7843..7673c53010 100644
--- a/sound/decoders/vorbis.cpp
+++ b/sound/decoders/vorbis.cpp
@@ -35,7 +35,7 @@
#include "sound/audiocd.h"
#ifdef USE_TREMOR
-#if defined(ANDROID) || defined(__GP32__) // custom libtremor locations
+#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 8ae2bad71a..929b1d8b12 100644
--- a/sound/midiparser.cpp
+++ b/sound/midiparser.cpp
@@ -67,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)
@@ -127,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;
@@ -172,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 {
@@ -232,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);
}
@@ -258,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);
}
}
}
@@ -266,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;
}
}
@@ -276,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));
@@ -329,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;
@@ -345,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);
}
}
}
@@ -399,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);
@@ -441,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/backends/platform/PalmOS/Src/args.h b/sound/null.h
index fa988fe35f..d9343701fa 100644
--- a/backends/platform/PalmOS/Src/args.h
+++ b/sound/null.h
@@ -8,37 +8,49 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along 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 ARGS_H
-#define ARGS_H
+#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) { }
+};
+
-#define MAX_ARG 25
+// Plugin interface
-#define ftrArgsData 1300
-#define ftrArgsCount 1301
-#define ftrVars 1302
-#define ftrStack 1303
+class NullMusicPlugin : public MusicPluginObject {
+public:
+ virtual const char *getName() const {
+ return _s("No music");
+ }
-Char **ArgsInit();
-void ArgsAdd(Char **argvP, const Char *argP, const Char *parmP, UInt8 *countArgP);
-void ArgsFree(Char **argvP);
-void ArgsSetOwner(Char **argvP, UInt16 owner);
+ virtual const char *getId() const {
+ return "null";
+ }
-void ArgsExportInit(Char **argvP, UInt32 countArg, Boolean arm);
-void ArgsExportRelease(Boolean arm);
+ 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..42b9be804e
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_audio.cpp
@@ -0,0 +1,1562 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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),
+ _cdaVolFlags(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(cdaSetVolume),
+ // 68
+ INTCB(cdaReset),
+ INTCB(notImpl),
+ INTCB(notImpl),
+ 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));
+ _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(uint32 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 > 0x5B8D80) {
+ _timer -= 0x5B8D80;
+
+ 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();
+ cdaReset();
+ 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_cdaReset(va_list &args) {
+ cdaReset();
+ return 0;
+}
+
+int TownsAudioInterface::intf_pcmUpdateEnvelopeGenerator(va_list &args) {
+ for (int i = 0; i < 8; i++)
+ pcmUpdateEnvelopeGenerator(i);
+ return 0;
+}
+
+int TownsAudioInterface::intf_cdaSetVolume(va_list &args) {
+ int mode = va_arg(args, int);
+ int left = va_arg(args, int);
+ int right = va_arg(args, int);
+
+ // calculate mixer balance value
+ int8 balance = right - left;
+
+ if (left & 0xff80 || right & 0xff80)
+ return 3;
+
+ static const uint8 flags[] = { 0x0C, 0x30, 0x40, 0x80 };
+
+ //int a = (mode & 0x40) ? 4 : 0;
+ int b = mode & 3;
+ left = (left & 0x7e) >> 1;
+ right = (right & 0x7e) >> 1;
+
+ if (mode & 0x40)
+ _cdaVolFlags |= flags[b];
+ else
+ _cdaVolFlags &= ~flags[b];
+
+ if (mode > 1) {
+ // Unknown purpose / TODO
+
+ } else if (mode == 1) {
+ // FM Towns seems to support volumes of 0 - 63 for each channel.
+ // We recalculate sane values for out 0 to 255 volume range.
+
+ int vl = (int)(((float)left * 255.0f) / 63.0f);
+ int vr = (int)(((float)right * 255.0f) / 63.0f);
+ AudioCD.setVolume((vl + vr) >> 1);
+ AudioCD.setBalance(balance);
+
+ } else {
+ // Unknown purpose / TODO
+ }
+
+ 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::cdaReset() {
+
+}
+
+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 = 0;
+
+ 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..212c00c40f
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_audio.h
@@ -0,0 +1,176 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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(uint32 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_cdaSetVolume(va_list &args);
+ int intf_cdaReset(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 cdaReset();
+
+ uint8 _cdaVolFlags;
+
+ const float _baserate;
+ uint32 _timerBase;
+ uint32 _tickLength;
+ uint32 _timer;
+
+ uint16 _musicVolume;
+ uint16 _sfxVolume;
+ uint32 _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..e23d5bcb36
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_euphony.cpp
@@ -0,0 +1,903 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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::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::cdaSetVolume(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::chanLevel(int tableEntry, int val) {
+ if (tableEntry > 31)
+ return 3;
+ if (val <= 40)
+ _tLevel[tableEntry] = (int8)(val & 0xff);
+ return 0;
+}
+
+int TownsEuphonyDriver::chanTranspose(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, prepTranspose(note));
+ sendEvent(mode, prepVelo(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, prepTranspose(_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::prepTranspose(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::prepVelo(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..2026a299c1
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_euphony.h
@@ -0,0 +1,185 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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();
+
+ 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 cdaSetVolume(int mode, int volLeft, int volRight);
+
+ int chanEnable(int tableEntry, int val);
+ int chanMode(int tableEntry, int val);
+ int chanOrdr(int tableEntry, int val);
+ int chanLevel(int tableEntry, int val);
+ int chanTranspose(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 prepTranspose(uint8 in);
+ uint8 prepVelo(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..507c8e159a
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.cpp
@@ -0,0 +1,1510 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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 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;
+ int32 _currentLevel;
+
+ struct EvpState {
+ uint8 rate;
+ uint8 shift;
+ } fs_a, fs_d, fs_s, fs_r;
+};
+
+TownsPC98_FmSynthOperator::TownsPC98_FmSynthOperator(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(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 > 0x5B8D80) {
+ _timer -= 0x5B8D80;
+ ++_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);
+ ~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;
+
+ 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);
+ ~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;
+
+ uint8 **_reg;
+
+ uint16 _volumeA;
+ uint16 _volumeB;
+ int _volMaskA;
+ int _volMaskB;
+
+ bool _ready;
+};
+
+TownsPC98_FmSynthSquareSineSource::TownsPC98_FmSynthSquareSineSource(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),
+ _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 > 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;
+ 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) :
+ _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 > 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;
+
+ 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),
+ _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, _oprRates, _oprRateshift, _oprAttackDecay, _oprFrq, _oprSinTbl, _oprLevelOut, _oprDetune);
+ }
+
+ if (_numSSG) {
+ _ssg = new TownsPC98_FmSynthSquareSineSource(_timerbase);
+ _ssg->init(&_ssgTables[0], &_ssgTables[16]);
+ }
+
+ if (_hasPercussion) {
+ _prc = new TownsPC98_FmSynthPercussionSource(_timerbase);
+ _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..34ee2ce7b8
--- /dev/null
+++ b/sound/softsynth/fmtowns_pc98/towns_pc98_fmsynth.h
@@ -0,0 +1,176 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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;
+
+ 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..38fc60763e 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 = 71
};
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 },
@@ -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..25a950935b 100644
--- a/tools/create_kyradat/create_kyradat.h
+++ b/tools/create_kyradat/create_kyradat.h
@@ -138,6 +138,8 @@ enum kExtractID {
k1CreditsStrings,
+ k1TownsMusicFadeTable,
+ k1TownsMusicFadeTable,
k1TownsSFXwdTable,
k1TownsSFXbtTable,
k1TownsCDATable,
diff --git a/tools/create_kyradat/games.cpp b/tools/create_kyradat/games.cpp
index 9976451067..1bd7d31648 100644
--- a/tools/create_kyradat/games.cpp
+++ b/tools/create_kyradat/games.cpp
@@ -411,6 +411,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..dc8163901d 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 } } } },
@@ -1823,6 +1829,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 f418971239..1c395b01aa 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);
@@ -835,11 +836,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
@@ -1323,7 +1327,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());
@@ -1345,7 +1349,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,
@@ -1648,7 +1652,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"
@@ -1661,7 +1665,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"
@@ -1678,6 +1682,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"
@@ -1896,12 +1901,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
@@ -2046,38 +2045,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();
@@ -2104,6 +2106,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 bff1251f7a..f59c68021a 100755
--- a/tools/credits.pl
+++ b/tools/credits.pl
@@ -698,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", "");
@@ -775,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");
@@ -854,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();
@@ -922,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");
@@ -933,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 6823607b27..7d76b7541d 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 896a2e504b..2c62e427ea 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 0637c386d7..c3e48d6c5a 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
@@ -588,7 +595,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
@@ -601,7 +608,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
@@ -654,13 +661,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
@@ -752,10 +759,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
@@ -834,7 +841,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
@@ -853,7 +860,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