aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS25
-rw-r--r--Makefile2
-rw-r--r--Makefile.common1
-rw-r--r--NEWS25
-rw-r--r--backends/events/sdl/sdl-events.cpp1
-rw-r--r--backends/events/symbiansdl/symbiansdl-events.cpp3
-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/psp/psp-stream.cpp14
-rw-r--r--backends/graphics/graphics.h2
-rw-r--r--backends/graphics/opengl/opengl-graphics.h2
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.cpp2
-rw-r--r--backends/graphics/openglsdl/openglsdl-graphics.h2
-rw-r--r--backends/graphics/sdl/sdl-graphics.cpp133
-rw-r--r--backends/graphics/sdl/sdl-graphics.h9
-rw-r--r--backends/keymapper/remap-dialog.cpp14
-rw-r--r--backends/midi/alsa.cpp13
-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.cpp15
-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.cpp13
-rw-r--r--backends/midi/zodiac.cpp13
-rw-r--r--backends/modular-backend.cpp4
-rw-r--r--backends/modular-backend.h2
-rw-r--r--backends/module.mk1
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp6
-rw-r--r--backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp2
-rw-r--r--backends/platform/PalmOS/Src/launcher/launch.cpp2
-rw-r--r--backends/platform/android/README.build75
-rw-r--r--backends/platform/android/android.cpp161
-rw-r--r--backends/platform/android/android.mk9
-rw-r--r--backends/platform/android/module.mk22
-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/video.cpp334
-rw-r--r--backends/platform/android/video.h140
-rw-r--r--backends/platform/dc/dc.h2
-rw-r--r--backends/platform/dc/display.cpp2
-rw-r--r--backends/platform/ds/arm7/source/main.cpp24
-rw-r--r--backends/platform/ds/arm9/makefile173
-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.cpp74
-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.h49
-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.mk161
-rw-r--r--backends/platform/ds/module.mk72
-rwxr-xr-xbackends/platform/gp2x/build/bundle.sh50
-rwxr-xr-xbackends/platform/gp2x/gp2x-bundle.mk60
-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/iphone/osys_events.cpp5
-rw-r--r--backends/platform/psp/Makefile7
-rw-r--r--backends/platform/psp/README.PSP2
-rw-r--r--backends/platform/psp/README.PSP.in2
-rw-r--r--backends/platform/psp/display_manager.cpp18
-rw-r--r--backends/platform/psp/display_manager.h20
-rw-r--r--backends/platform/psp/module.mk1
-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.cpp3
-rw-r--r--backends/platform/psp/psploader.cpp141
-rw-r--r--backends/platform/psp/rtc.cpp87
-rw-r--r--backends/platform/psp/rtc.h50
-rw-r--r--backends/platform/psp/thread.cpp174
-rw-r--r--backends/platform/psp/thread.h48
-rw-r--r--backends/platform/psp/trace.cpp11
-rw-r--r--backends/platform/psp/trace.h6
-rw-r--r--backends/platform/symbian/src/SymbianActions.cpp41
-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/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.cpp6
-rw-r--r--base/internal_version.h5
-rw-r--r--base/internal_version.h.in5
-rw-r--r--base/main.cpp39
-rw-r--r--base/plugins.cpp5
-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/macresman.cpp10
-rw-r--r--common/messages.cpp2063
-rw-r--r--common/module.mk1
-rw-r--r--common/savefile.h4
-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.cpp9
-rw-r--r--common/translation.cpp217
-rw-r--r--common/translation.h145
-rw-r--r--common/unzip.cpp49
-rw-r--r--common/unzip.h4
-rw-r--r--common/util.cpp156
-rw-r--r--common/util.h21
-rwxr-xr-xconfigure135
-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/iphone/Info.plist5
-rw-r--r--dists/iphone/icon-72.pngbin0 -> 5668 bytes
-rw-r--r--engines/advancedDetector.cpp58
-rw-r--r--engines/advancedDetector.h15
-rw-r--r--engines/agi/agi.cpp35
-rw-r--r--engines/agi/agi.h295
-rw-r--r--engines/agi/console.cpp17
-rw-r--r--engines/agi/cycle.cpp23
-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.cpp1433
-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.h73
-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.cpp70
-rw-r--r--engines/agi/sprite.h4
-rw-r--r--engines/agi/text.cpp14
-rw-r--r--engines/agi/view.cpp33
-rw-r--r--engines/agi/view.h1
-rw-r--r--engines/agos/agos.cpp38
-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.cpp8
-rw-r--r--engines/agos/gfx.cpp6
-rw-r--r--engines/agos/icons.cpp2
-rw-r--r--engines/agos/input.cpp16
-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/detection.cpp497
-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.cpp4
-rw-r--r--engines/cine/saveload.h2
-rw-r--r--engines/cruise/decompiler.cpp2
-rw-r--r--engines/cruise/detection.cpp6
-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.cpp6
-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/script.cpp8
-rw-r--r--engines/draci/sound.cpp203
-rw-r--r--engines/draci/sound.h130
-rw-r--r--engines/drascula/actors.cpp3
-rw-r--r--engines/drascula/animation.cpp142
-rw-r--r--engines/drascula/console.cpp (renamed from engines/sci/graphics/gui32.h)61
-rw-r--r--engines/drascula/console.h (renamed from backends/platform/ds/arm9/source/portdefs.cpp)44
-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.cpp1
-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.cpp4
-rw-r--r--engines/gob/inter_v1.cpp11
-rw-r--r--engines/groovie/cursor.cpp13
-rw-r--r--engines/groovie/detection.cpp6
-rw-r--r--engines/groovie/font.cpp1
-rw-r--r--engines/groovie/groovie.cpp12
-rw-r--r--engines/groovie/groovie.h2
-rw-r--r--engines/groovie/music.cpp98
-rw-r--r--engines/groovie/music.h3
-rw-r--r--engines/groovie/script.cpp6
-rw-r--r--engines/kyra/detection.cpp1175
-rw-r--r--engines/kyra/detection_tables.h1192
-rw-r--r--engines/kyra/kyra_v1.cpp17
-rw-r--r--engines/kyra/sound_intern.h4
-rw-r--r--engines/kyra/sound_towns.cpp251
-rw-r--r--engines/lure/detection.cpp6
-rw-r--r--engines/lure/sound.cpp8
-rw-r--r--engines/m4/animation.cpp151
-rw-r--r--engines/m4/animation.h17
-rw-r--r--engines/m4/assets.cpp86
-rw-r--r--engines/m4/assets.h23
-rw-r--r--engines/m4/console.cpp2
-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.cpp229
-rw-r--r--engines/m4/graphics.h25
-rw-r--r--engines/m4/m4.cpp42
-rw-r--r--engines/m4/m4.h12
-rw-r--r--engines/m4/mads_anim.cpp93
-rw-r--r--engines/m4/mads_anim.h3
-rw-r--r--engines/m4/mads_logic.cpp259
-rw-r--r--engines/m4/mads_logic.h9
-rw-r--r--engines/m4/mads_menus.cpp19
-rw-r--r--engines/m4/mads_player.cpp454
-rw-r--r--engines/m4/mads_player.h88
-rw-r--r--engines/m4/mads_scene.cpp223
-rw-r--r--engines/m4/mads_scene.h36
-rw-r--r--engines/m4/mads_views.cpp158
-rw-r--r--engines/m4/mads_views.h25
-rw-r--r--engines/m4/midi.cpp2
-rw-r--r--engines/m4/module.mk1
-rw-r--r--engines/m4/scene.cpp1
-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/detection.cpp6
-rw-r--r--engines/made/made.cpp8
-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/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.cpp8
-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/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.cpp274
-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.cpp18
-rw-r--r--engines/saga/saga.h1
-rw-r--r--engines/saga/scene.cpp12
-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.cpp935
-rw-r--r--engines/sci/console.h13
-rw-r--r--engines/sci/debug.h7
-rw-r--r--engines/sci/decompressor.cpp16
-rw-r--r--engines/sci/detection.cpp120
-rw-r--r--engines/sci/detection_tables.h69
-rw-r--r--engines/sci/engine/features.cpp116
-rw-r--r--engines/sci/engine/features.h6
-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.cpp1390
-rw-r--r--engines/sci/engine/kernel.h227
-rw-r--r--engines/sci/engine/kernel32.cpp149
-rw-r--r--engines/sci/engine/kevent.cpp27
-rw-r--r--engines/sci/engine/kfile.cpp412
-rw-r--r--engines/sci/engine/kgraphics.cpp696
-rw-r--r--engines/sci/engine/klists.cpp223
-rw-r--r--engines/sci/engine/kmath.cpp29
-rw-r--r--engines/sci/engine/kmenu.cpp8
-rw-r--r--engines/sci/engine/kmisc.cpp87
-rw-r--r--engines/sci/engine/kmovement.cpp117
-rw-r--r--engines/sci/engine/kparse.cpp6
-rw-r--r--engines/sci/engine/kpathing.cpp258
-rw-r--r--engines/sci/engine/kscripts.cpp115
-rw-r--r--engines/sci/engine/ksound.cpp104
-rw-r--r--engines/sci/engine/kstring.cpp29
-rw-r--r--engines/sci/engine/message.cpp7
-rw-r--r--engines/sci/engine/savegame.cpp472
-rw-r--r--engines/sci/engine/savegame.h8
-rw-r--r--engines/sci/engine/script.cpp786
-rw-r--r--engines/sci/engine/script.h359
-rw-r--r--engines/sci/engine/scriptdebug.cpp184
-rw-r--r--engines/sci/engine/seg_manager.cpp439
-rw-r--r--engines/sci/engine/seg_manager.h125
-rw-r--r--engines/sci/engine/segment.cpp512
-rw-r--r--engines/sci/engine/segment.h247
-rw-r--r--engines/sci/engine/selector.cpp39
-rw-r--r--engines/sci/engine/selector.h127
-rw-r--r--engines/sci/engine/state.cpp117
-rw-r--r--engines/sci/engine/state.h82
-rw-r--r--engines/sci/engine/static_selectors.cpp41
-rw-r--r--engines/sci/engine/vm.cpp1106
-rw-r--r--engines/sci/engine/vm.h372
-rw-r--r--engines/sci/engine/vm_types.h7
-rw-r--r--engines/sci/event.cpp70
-rw-r--r--engines/sci/event.h57
-rw-r--r--engines/sci/graphics/animate.cpp466
-rw-r--r--engines/sci/graphics/animate.h20
-rw-r--r--engines/sci/graphics/cache.cpp2
-rw-r--r--engines/sci/graphics/cache.h2
-rw-r--r--engines/sci/graphics/compare.cpp36
-rw-r--r--engines/sci/graphics/compare.h2
-rw-r--r--engines/sci/graphics/controls.cpp1
-rw-r--r--engines/sci/graphics/coordadjuster.cpp1
-rw-r--r--engines/sci/graphics/cursor.cpp60
-rw-r--r--engines/sci/graphics/cursor.h4
-rw-r--r--engines/sci/graphics/font.cpp7
-rw-r--r--engines/sci/graphics/fontsjis.h6
-rw-r--r--engines/sci/graphics/frameout.cpp219
-rw-r--r--engines/sci/graphics/frameout.h9
-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/maciconbar.cpp1
-rw-r--r--engines/sci/graphics/menu.cpp88
-rw-r--r--engines/sci/graphics/menu.h11
-rw-r--r--engines/sci/graphics/paint.h2
-rw-r--r--engines/sci/graphics/paint16.cpp123
-rw-r--r--engines/sci/graphics/paint16.h27
-rw-r--r--engines/sci/graphics/paint32.cpp7
-rw-r--r--engines/sci/graphics/paint32.h3
-rw-r--r--engines/sci/graphics/palette.cpp456
-rw-r--r--engines/sci/graphics/palette.h49
-rw-r--r--engines/sci/graphics/picture.cpp8
-rw-r--r--engines/sci/graphics/portrait.cpp12
-rw-r--r--engines/sci/graphics/portrait.h5
-rw-r--r--engines/sci/graphics/ports.cpp47
-rw-r--r--engines/sci/graphics/ports.h3
-rw-r--r--engines/sci/graphics/robot.cpp8
-rw-r--r--engines/sci/graphics/robot.h6
-rw-r--r--engines/sci/graphics/screen.cpp139
-rw-r--r--engines/sci/graphics/screen.h47
-rw-r--r--engines/sci/graphics/text16.cpp90
-rw-r--r--engines/sci/graphics/text16.h6
-rw-r--r--engines/sci/graphics/transitions.cpp77
-rw-r--r--engines/sci/graphics/transitions.h3
-rw-r--r--engines/sci/graphics/view.cpp397
-rw-r--r--engines/sci/graphics/view.h27
-rw-r--r--engines/sci/module.mk6
-rw-r--r--engines/sci/parser/vocabulary.cpp53
-rw-r--r--engines/sci/resource.cpp737
-rw-r--r--engines/sci/resource.h332
-rw-r--r--engines/sci/resource_audio.cpp294
-rw-r--r--engines/sci/resource_intern.h193
-rw-r--r--engines/sci/sci.cpp432
-rw-r--r--engines/sci/sci.h176
-rw-r--r--engines/sci/sound/audio.cpp83
-rw-r--r--engines/sci/sound/audio.h5
-rw-r--r--engines/sci/sound/drivers/adlib.cpp14
-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.h1
-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.cpp659
-rw-r--r--engines/sci/sound/midiparser_sci.h40
-rw-r--r--engines/sci/sound/music.cpp266
-rw-r--r--engines/sci/sound/music.h60
-rw-r--r--engines/sci/sound/soundcmd.cpp919
-rw-r--r--engines/sci/sound/soundcmd.h97
-rw-r--r--engines/scumm/charset.cpp7
-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/saveload.cpp4
-rw-r--r--engines/scumm/script_v5.cpp11
-rw-r--r--engines/scumm/scumm-md5.h47
-rw-r--r--engines/scumm/scumm.cpp38
-rw-r--r--engines/scumm/sound.cpp2
-rw-r--r--engines/scumm/string.cpp2
-rw-r--r--engines/scumm/verbs.h2
-rw-r--r--engines/sky/sky.cpp10
-rw-r--r--engines/sword1/music.cpp2
-rw-r--r--engines/teenagent/detection.cpp4
-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/pcode.cpp7
-rw-r--r--engines/tinsel/tinlib.cpp2
-rw-r--r--engines/tinsel/tinsel.cpp8
-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/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/video/codecs/qdm2.cpp159
-rw-r--r--graphics/video/codecs/qdm2.h2
-rw-r--r--graphics/video/qt_decoder.cpp6
-rw-r--r--gui/EditTextWidget.cpp8
-rw-r--r--gui/EditTextWidget.h4
-rw-r--r--gui/GuiManager.cpp47
-rw-r--r--gui/GuiManager.h10
-rw-r--r--gui/KeysDialog.cpp27
-rw-r--r--gui/ListWidget.cpp8
-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.cpp157
-rw-r--r--gui/ThemeEngine.h27
-rw-r--r--gui/ThemeParser.cpp3
-rw-r--r--gui/about.cpp20
-rw-r--r--gui/browser.cpp8
-rw-r--r--gui/chooser.cpp5
-rw-r--r--gui/console.cpp4
-rw-r--r--gui/credits.h25
-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.cpp157
-rw-r--r--gui/massadd.cpp17
-rw-r--r--gui/message.cpp4
-rw-r--r--gui/options.cpp438
-rw-r--r--gui/options.h20
-rw-r--r--gui/saveload.cpp35
-rw-r--r--gui/themebrowser.cpp8
-rw-r--r--gui/themes/default.inc1516
-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 -> 56900 bytes
-rw-r--r--gui/themes/scummclassic/classic_gfx.stx90
-rw-r--r--gui/themes/scummclassic/classic_layout.stx59
-rw-r--r--gui/themes/scummclassic/classic_layout_lowres.stx78
-rw-r--r--gui/themes/scummmodern.zipbin158233 -> 164185 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.stx63
-rw-r--r--gui/themes/scummmodern/scummmodern_layout.stx63
-rw-r--r--gui/themes/scummmodern/scummmodern_layout_lowres.stx80
-rw-r--r--gui/widget.cpp263
-rw-r--r--gui/widget.h106
-rw-r--r--po/POTFILES45
-rw-r--r--po/ca_ES.po1447
-rw-r--r--po/de_DE.po1442
-rw-r--r--po/fr_FR.po1486
-rw-r--r--po/hu_HU.po1385
-rw-r--r--po/it_IT.po1362
-rw-r--r--po/module.mk43
-rw-r--r--po/remove-potcdate.sed19
-rw-r--r--po/ru_RU.po1361
-rw-r--r--po/scummvm.pot1341
-rw-r--r--ports.mk10
-rw-r--r--sound/audiostream.cpp6
-rw-r--r--sound/audiostream.h48
-rw-r--r--sound/decoders/adpcm.h2
-rw-r--r--sound/decoders/aiff.cpp11
-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/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.cpp402
-rw-r--r--sound/mididrv.h152
-rw-r--r--sound/midiparser.cpp22
-rw-r--r--sound/midiparser.h8
-rw-r--r--sound/mods/protracker.h2
-rw-r--r--sound/musicplugin.cpp20
-rw-r--r--sound/musicplugin.h32
-rw-r--r--sound/null.cpp54
-rw-r--r--sound/null.h56
-rw-r--r--sound/softsynth/adlib.cpp16
-rw-r--r--sound/softsynth/fluidsynth.cpp13
-rw-r--r--sound/softsynth/mt32.cpp23
-rw-r--r--sound/softsynth/pcspk.cpp57
-rw-r--r--sound/softsynth/sid.cpp2
-rw-r--r--sound/softsynth/ym2612.cpp16
-rw-r--r--tools/convbdf.c8
-rw-r--r--tools/create_msvc/create_msvc.cpp13
-rwxr-xr-xtools/credits.pl31
-rw-r--r--tools/make-scumm-fontdata.c2
-rw-r--r--tools/md5table.c1
-rw-r--r--tools/module.mk1
-rwxr-xr-xtools/po2c260
-rw-r--r--tools/scumm-md5.txt43
608 files changed, 146272 insertions, 30875 deletions
diff --git a/AUTHORS b/AUTHORS
index 28d71b3698..528674d59f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -318,6 +318,29 @@ 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
+
Websites (design)
-----------------
Dobo Balazs - Website design
@@ -395,7 +418,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 20be8e1bf6..e2f14810b2 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 5796a7f885..908c121721 100644
--- a/NEWS
+++ b/NEWS
@@ -8,11 +8,36 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
General:
- 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.
+ 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.
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index 96def04e25..df9efe54b1 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -213,6 +213,7 @@ bool SdlEventManager::pollSdlEvent(Common::Event &event) {
}
SDL_Event ev;
+ ev.type = SDL_NOEVENT;
while (SDL_PollEvent(&ev)) {
preprocessEvents(&ev);
if (dispatchSDLEvent(ev, event))
diff --git a/backends/events/symbiansdl/symbiansdl-events.cpp b/backends/events/symbiansdl/symbiansdl-events.cpp
index af57e81ccc..2d144f9ad9 100644
--- a/backends/events/symbiansdl/symbiansdl-events.cpp
+++ b/backends/events/symbiansdl/symbiansdl-events.cpp
@@ -28,6 +28,7 @@
#include "backends/events/symbiansdl/symbiansdl-events.h"
#include "backends/platform/symbian/src/SymbianActions.h"
#include "gui/message.h"
+#include "common/translation.h"
#include <bautils.h>
@@ -183,7 +184,7 @@ bool SymbianSdlEventManager::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)
g_system->quit();
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/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/graphics/graphics.h b/backends/graphics/graphics.h
index 0ea425c9bc..9eb354aee4 100644
--- a/backends/graphics/graphics.h
+++ b/backends/graphics/graphics.h
@@ -48,7 +48,7 @@ public:
virtual int getGraphicsMode() const = 0;
#ifdef USE_RGB_COLOR
virtual Graphics::PixelFormat getScreenFormat() const = 0;
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats() = 0;
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0;
#endif
virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL) = 0;
virtual int getScreenChangeID() const = 0;
diff --git a/backends/graphics/opengl/opengl-graphics.h b/backends/graphics/opengl/opengl-graphics.h
index f12e4b45d7..17d0b842e9 100644
--- a/backends/graphics/opengl/opengl-graphics.h
+++ b/backends/graphics/opengl/opengl-graphics.h
@@ -53,7 +53,7 @@ public:
virtual int getGraphicsMode() const;
#ifdef USE_RGB_COLOR
virtual Graphics::PixelFormat getScreenFormat() const;
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats() = 0;
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const = 0;
#endif
virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL);
virtual int getScreenChangeID() const;
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.cpp b/backends/graphics/openglsdl/openglsdl-graphics.cpp
index 6207561c07..b12c3af5cd 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.cpp
+++ b/backends/graphics/openglsdl/openglsdl-graphics.cpp
@@ -57,7 +57,7 @@ const Graphics::PixelFormat RGBList[] = {
Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0), // RGBA4444
};
-Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormats() {
+Common::List<Graphics::PixelFormat> OpenGLSdlGraphicsManager::getSupportedFormats() const {
static Common::List<Graphics::PixelFormat> list;
static bool inited = false;
diff --git a/backends/graphics/openglsdl/openglsdl-graphics.h b/backends/graphics/openglsdl/openglsdl-graphics.h
index 0f69793c1b..56aae27ab7 100644
--- a/backends/graphics/openglsdl/openglsdl-graphics.h
+++ b/backends/graphics/openglsdl/openglsdl-graphics.h
@@ -45,7 +45,7 @@ public:
virtual void init();
#ifdef USE_RGB_COLOR
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats();
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
#endif
virtual void warpMouse(int x, int y);
diff --git a/backends/graphics/sdl/sdl-graphics.cpp b/backends/graphics/sdl/sdl-graphics.cpp
index a554479756..e8251a779d 100644
--- a/backends/graphics/sdl/sdl-graphics.cpp
+++ b/backends/graphics/sdl/sdl-graphics.cpp
@@ -29,6 +29,7 @@
#include "common/system.h"
#include "common/config-manager.h"
#include "common/mutex.h"
+#include "common/translation.h"
#include "common/util.h"
#ifdef USE_RGB_COLOR
#include "common/list.h"
@@ -41,7 +42,7 @@
#include "backends/events/sdl/sdl-events.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},
@@ -97,11 +98,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");
@@ -359,45 +360,53 @@ OSystem::TransactionError SdlGraphicsManager::endGFXTransaction() {
}
#ifdef USE_RGB_COLOR
-const Graphics::PixelFormat RGBList[] = {
+Common::List<Graphics::PixelFormat> SdlGraphicsManager::getSupportedFormats() const {
+ assert(!_supportedFormats.empty());
+ return _supportedFormats;
+}
+
+void SdlGraphicsManager::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> SdlGraphicsManager::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) {
@@ -413,30 +422,30 @@ Common::List<Graphics::PixelFormat> SdlGraphicsManager::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
@@ -718,6 +727,10 @@ bool SdlGraphicsManager::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.
@@ -1531,6 +1544,10 @@ void SdlGraphicsManager::setMousePos(int x, int y) {
void SdlGraphicsManager::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);
diff --git a/backends/graphics/sdl/sdl-graphics.h b/backends/graphics/sdl/sdl-graphics.h
index 4ca92e9d30..0218be55dc 100644
--- a/backends/graphics/sdl/sdl-graphics.h
+++ b/backends/graphics/sdl/sdl-graphics.h
@@ -87,7 +87,7 @@ public:
virtual int getGraphicsMode() const;
#ifdef USE_RGB_COLOR
virtual Graphics::PixelFormat getScreenFormat() const { return _screenFormat; }
- virtual Common::List<Graphics::PixelFormat> getSupportedFormats();
+ virtual Common::List<Graphics::PixelFormat> getSupportedFormats() const;
#endif
virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format = NULL);
virtual int getScreenChangeID() const { return _screenChangeCount; }
@@ -160,6 +160,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/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..a82fffdf0d 100644
--- a/backends/midi/alsa.cpp
+++ b/backends/midi/alsa.cpp
@@ -269,7 +269,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
#define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
@@ -315,21 +315,12 @@ MusicDevices AlsaMusicPlugin::getDevices() const {
return devices;
}
-Common::Error AlsaMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error AlsaMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
*mididriver = new MidiDriver_ALSA();
return Common::kNoError;
}
-MidiDriver *MidiDriver_ALSA_create() {
- MidiDriver *mididriver;
-
- AlsaMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
//#if PLUGIN_ENABLED_DYNAMIC(ALSA)
//REGISTER_PLUGIN_DYNAMIC(ALSA, PLUGIN_TYPE_MUSIC, AlsaMusicPlugin);
//#else
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..b1815adee5 100644
--- a/backends/midi/seq.cpp
+++ b/backends/midi/seq.cpp
@@ -28,7 +28,7 @@
* both the QuickTime support and (vkeybd http://www.alsa-project.org/~iwai/alsa.html)
*/
-#if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__)
+#if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__) && !defined(__ANDROID__)
#include "common/util.h"
#include "sound/musicplugin.h"
@@ -184,7 +184,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 +195,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
index fe65d02c10..fb114d625c 100644
--- a/backends/midi/ypa1.cpp
+++ b/backends/midi/ypa1.cpp
@@ -117,7 +117,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices YamahaPa1MusicPlugin::getDevices() const {
@@ -128,21 +128,12 @@ MusicDevices YamahaPa1MusicPlugin::getDevices() const {
return devices;
}
-Common::Error YamahaPa1MusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error YamahaPa1MusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) 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
diff --git a/backends/midi/zodiac.cpp b/backends/midi/zodiac.cpp
index b9cb46912a..e848315ca4 100644
--- a/backends/midi/zodiac.cpp
+++ b/backends/midi/zodiac.cpp
@@ -135,7 +135,7 @@ public:
}
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
};
MusicDevices ZodiacMusicPlugin::getDevices() const {
@@ -146,21 +146,12 @@ MusicDevices ZodiacMusicPlugin::getDevices() const {
return devices;
}
-Common::Error ZodiacMusicPlugin::createInstance(MidiDriver **mididriver) const {
+Common::Error ZodiacMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) 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
diff --git a/backends/modular-backend.cpp b/backends/modular-backend.cpp
index 3a18014b3a..e7d0764c11 100644
--- a/backends/modular-backend.cpp
+++ b/backends/modular-backend.cpp
@@ -92,13 +92,15 @@ int ModularBackend::getGraphicsMode() const {
}
#ifdef USE_RGB_COLOR
+
Graphics::PixelFormat ModularBackend::getScreenFormat() const {
return _graphicsManager->getScreenFormat();
}
-Common::List<Graphics::PixelFormat> ModularBackend::getSupportedFormats() {
+Common::List<Graphics::PixelFormat> ModularBackend::getSupportedFormats() const {
return _graphicsManager->getSupportedFormats();
}
+
#endif
void ModularBackend::initSize(uint w, uint h, const Graphics::PixelFormat *format ) {
diff --git a/backends/modular-backend.h b/backends/modular-backend.h
index a60fccc876..63e13059cb 100644
--- a/backends/modular-backend.h
+++ b/backends/modular-backend.h
@@ -76,7 +76,7 @@ public:
virtual 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
virtual void initSize(uint width, uint height, const Graphics::PixelFormat *format = NULL);
virtual int getScreenChangeID() const;
diff --git a/backends/module.mk b/backends/module.mk
index 146253248b..801c98135f 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -29,6 +29,7 @@ MODULE_OBJS := \
graphics/gp2xwizsdl/gp2xwizsdl-graphics.o \
graphics/linuxmotosdl/linuxmotosdl-graphics.o \
graphics/opengl/glerrorcheck.o \
+ graphics/opengl/gltexture.o \
graphics/opengl/opengl-graphics.o \
graphics/openglsdl/openglsdl-graphics.o \
graphics/sdl/sdl-graphics.o \
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp b/backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp
index b4c1e222d0..9566a25311 100644
--- a/backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp
+++ b/backends/platform/PalmOS/Src/launcher/forms/formSkins.cpp
@@ -107,7 +107,7 @@ static void SkinsFormExit(Boolean bSave) {
listP = (ListType *)GetObjectPtr(SkinsSkinList);
selected = LstGetSelection(listP);
- if (bSave && selected == -1) { // may never occured...
+ if (bSave && selected == -1) { // may never occurred...
FrmCustomAlert(FrmWarnAlert, "You didn't select a skin.", 0, 0);
return;
}
@@ -164,7 +164,7 @@ static void SkinsFormBeam() {
listP = (ListType *)GetObjectPtr(SkinsSkinList);
selected = LstGetSelection(listP);
- if (selected == -1) { // may never occured...
+ if (selected == -1) { // may never occurred...
FrmCustomAlert(FrmWarnAlert, "You didn't select a skin.", 0, 0);
return;
}
@@ -187,7 +187,7 @@ static void SkinsFormDelete() {
listP = (ListType *)GetObjectPtr(SkinsSkinList);
selected = LstGetSelection(listP);
- if (selected == -1) { // may never occured...
+ if (selected == -1) { // may never occurred...
FrmCustomAlert(FrmInfoAlert, "You didn't select a skin.", 0, 0);
return;
}
diff --git a/backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp b/backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp
index 58eaa5b5fc..48399efa95 100644
--- a/backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp
+++ b/backends/platform/PalmOS/Src/launcher/forms/formmusic.cpp
@@ -258,7 +258,7 @@ static void MusicFormInit(UInt16 index) {
ogameInfoP = (GameInfoType *)MemHandleLock(recordH);
if (!ogameInfoP) {
- FrmCustomAlert(FrmErrorAlert, "An error occured.",0,0);
+ FrmCustomAlert(FrmErrorAlert, "An error occurred.",0,0);
return;
}
diff --git a/backends/platform/PalmOS/Src/launcher/launch.cpp b/backends/platform/PalmOS/Src/launcher/launch.cpp
index cb2d52b20e..d83a34e94c 100644
--- a/backends/platform/PalmOS/Src/launcher/launch.cpp
+++ b/backends/platform/PalmOS/Src/launcher/launch.cpp
@@ -468,7 +468,7 @@ Boolean StartScummVM(Int16 engine) {
return false;
}
- // reset mode if screen rotation occured (DIA only)
+ // reset mode if screen rotation occurred (DIA only)
if (!direct && OPTIONS_TST(kOptCollapsible)) {
UInt8 mode = PalmScreenSize(0,0, &(gVars->screenFullWidth), &(gVars->screenFullHeight));
OPTIONS_RST(kOptModeLandscape);
diff --git a/backends/platform/android/README.build b/backends/platform/android/README.build
index fa56bfc180..3d1cf433a7 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.
-- Build your own arm-android-eabi toolchain from GCC source.
+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.
-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
+ - Build your own arm-*-linux-androideabi toolchain from GCC source.
+
+This is lots of fun, but will become significantly easier once gcc-4.6
+is released. In the interim, I suggest using my precompiled Android
+openembedded-based toolchain:
+ wget http://commondatastorage.googleapis.com/anr/sdk/android-2.2-i686-linux-armv5te-linux-androideabi-toolchain-android.tar.bz2
+ sudo tar jxf android-2.2-i686-linux-armv5te-linux-androideabi-toolchain-android.tar.bz2 -C /
+ . /usr/local/android/arm/environment-setup
Alternatively, do a websearch - there are several other cross-compile
toolchains around.
@@ -63,18 +67,25 @@ toolchains around.
Building ScummVM
================
+Apply the theme engine patch:
+
+ patch -p1 < backends/platform/android/scummvm-android-themeengine.patch
+
+(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..c7b98b996d 100644
--- a/backends/platform/android/module.mk
+++ b/backends/platform/android/module.mk
@@ -39,14 +39,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 +71,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/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/dc.h b/backends/platform/dc/dc.h
index 8a122ebb27..e87a0a8c90 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
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/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..079e23aec0 100644
--- a/backends/platform/ds/arm9/makefile
+++ b/backends/platform/ds/arm9/makefile
@@ -113,9 +113,6 @@ ifdef DS_BUILD_A
DEFINES = -DDS_SCUMM_BUILD -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
@@ -202,7 +199,6 @@ endif
#endif
ARM7BIN := -7 $(CURDIR)/../../arm7/arm7.bin
-ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;"
CC = arm-eabi-gcc
CXX = arm-eabi-g++
@@ -248,9 +244,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
@@ -260,7 +253,7 @@ endif
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 +265,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 +275,69 @@ 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)/../../../fs/ds/ds-fs.o \
+ $(portdir)/source/gbampsave.o \
+ $(portdir)/source/scummhelp.o \
+ $(portdir)/source/osystem_ds.o \
+ $(portdir)/source/touchkeyboard.o \
+ $(portdir)/source/zipreader.o \
+ $(portdir)/source/dsoptions.o \
+ $(portdir)/source/keys.o \
+ $(portdir)/source/wordcompletion.o \
+ $(portdir)/source/interrupt.o
ifdef USE_PROFILER
PORT_OBJS += $(portdir)/source/profiler/cyg-profile.o
endif
-DATA_OBJS := $(portdir)/data/icons.o $(portdir)/data/keyboard.o $(portdir)/data/keyboard_pal.o $(portdir)/data/default_font.o $(portdir)/data/8x8font_tga.o
-
-COMPRESSOR_OBJS :=
-#$(portdir)/source/compressor/lz.o
+DATA_OBJS :=
+ $(portdir)/data/icons.o \
+ $(portdir)/data/keyboard.o \
+ $(portdir)/data/keyboard_pal.o \
+ $(portdir)/data/default_font.o \
+ $(portdir)/data/8x8font_tga.o
+
+FAT_OBJS :=
+ $(portdir)/source/fat/disc_io.o \
+ $(portdir)/source/fat/gba_nds_fat.o \
+ $(portdir)/source/fat/io_fcsr.o \
+ $(portdir)/source/fat/io_m3cf.o \
+ $(portdir)/source/fat/io_mpcf.o \
+ $(portdir)/source/fat/io_sccf.o \
+ $(portdir)/source/fat/io_m3sd.o \
+ $(portdir)/source/fat/io_nmmc.o \
+ $(portdir)/source/fat/io_scsd.o \
+ $(portdir)/source/fat/io_scsd_asm.o \
+ $(portdir)/source/fat/io_njsd.o \
+ $(portdir)/source/fat/io_mmcf.o \
+ $(portdir)/source/fat/io_sd_common.o \
+ $(portdir)/source/fat/io_m3_common.o \
+ $(portdir)/source/fat/io_dldi.o \
+ $(portdir)/source/fat/m3sd.o
-FAT_OBJS := $(portdir)/source/fat/disc_io.o $(portdir)/source/fat/gba_nds_fat.o\
- $(portdir)/source/fat/io_fcsr.o $(portdir)/source/fat/io_m3cf.o\
- $(portdir)/source/fat/io_mpcf.o $(portdir)/source/fat/io_sccf.o\
- $(portdir)/source/fat/io_m3sd.o\
- $(portdir)/source/fat/io_nmmc.o $(portdir)/source/fat/io_scsd.o \
- $(portdir)/source/fat/io_scsd_asm.o \
- $(portdir)/source/fat/io_njsd.o \
- $(portdir)/source/fat/io_mmcf.o \
- $(portdir)/source/fat/io_sd_common.o \
- $(portdir)/source/fat/io_m3_common.o \
- $(portdir)/source/fat/io_dldi.o \
- $(portdir)/source/fat/m3sd.o
-
-
-# $(portdir)/source/fat/io_cf_common.o $(portdir)/source/fat/io_m3_common.o\
-# $(portdir)/source/fat/io_sd_common.o $(portdir)/source/fat/io_scsd_s.o \
-# $(portdir)/source/fat/io_sc_common.o $(portdir)/source/fat/io_sd_common.o
-
-LIBCARTRESET_OBJS :=
-#$(portdir)/source/libcartreset/cartreset.o
# Files in this list will be optimisied for speed, otherwise they will be optimised for space
-OPTLIST := actor.cpp ds_main.cpp osystem_ds.cpp blitters.cpp mame.cpp rate.cpp isomap.cpp image.cpp gfx.cpp sprite.cpp actor_path.cpp actor_walk.cpp script.cpp
+OPTLIST := actor.cpp dsmain.cpp osystem_ds.cpp blitters.cpp mame.cpp rate.cpp isomap.cpp image.cpp gfx.cpp sprite.cpp actor_path.cpp actor_walk.cpp script.cpp
#OPTLIST :=
# Compiler options for files which should be optimised for speed
ifdef DS_BUILD_E
-# Another attempt to save some RAM in ITE
-OPT_SPEED := -O3 -mthumb
+ # Another attempt to save some RAM in ITE
+ OPT_SPEED := -O3 -mthumb
else
-#OPT_SPEED := -O3
-
-OPT_SPEED := -Os -mthumb
-
+ OPT_SPEED := -O3
endif
# Compiler options for files which should be optimised for space
OPT_SIZE := -Os -mthumb
-#-mthumb -fno-gcse -fno-schedule-insns2
-
-
-OBJS := $(DATA_OBJS) $(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..cc89c41017 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,8 +121,8 @@ 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);
@@ -125,7 +130,7 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
#ifdef DS_SCUMM_BUILD
if (!DS::isGBAMPAvailable()) {
-// addButton(this, 100, 140, "Delete Save", 'dels', 'D');
+// addButton(this, 100, 140, "Delete Save", 0, 'dels', 'D');
}
#endif
@@ -133,7 +138,7 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
//#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 +369,7 @@ void showOptionsDialog() {
DS::displayMode16Bit();
- DSOptionsDialog* d = new DSOptionsDialog();
+ DSOptionsDialog *d = new DSOptionsDialog();
d->runModal();
delete d;
@@ -418,7 +423,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 +441,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.h b/backends/platform/ds/arm9/source/portdefs.h
index 5472b711b8..bdb42993d1 100644
--- a/backends/platform/ds/arm9/source/portdefs.h
+++ b/backends/platform/ds/arm9/source/portdefs.h
@@ -8,39 +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 _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 "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 +37,20 @@ 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!")
#define NO_DEBUG_MSGS
-
// This is defined in dsmain.cpp
#ifdef __cplusplus
extern "C" {
@@ -76,15 +65,17 @@ 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__)
+#define assert(s) \
+ do { \
+ if (!(s)) \
+ consolePrintf("Assertion failed: '##s##' at file %s, line %d\n", __FILE__, __LINE__); \
+ } while (0)
//#include "ds-fs.h"
//#define debug(fmt, ...) consolePrintf(fmt, ##__VA_ARGS__)
//#define debug(fmt, ...) debug(0, fmt, ##__VA_ARGS__)
-#define ITCM_DATA __attribute__((section(".itcm")))
-
// 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
// a more conventional form of input where the menus can be clicked on.
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..27309663d1 100644
--- a/backends/platform/ds/ds.mk
+++ b/backends/platform/ds/ds.mk
@@ -1,12 +1,64 @@
-# 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
+#
+# 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.
+# * ...
+
+# 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.
-# 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
@@ -14,31 +66,71 @@ OPT_SPEED := -O3
# 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: speed original list contained three more files that should be optimized
+# for speed: actor.cpp gfx.cpp sprite.cpp -- but there are many files with these
+# names, which are the "right" ones?
+$(ndsdir)/arm9/source/dsmain.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+$(ndsdir)/arm9/source/osystem_ds.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+$(ndsdir)/arm9/source/blitters.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+$(ndsdir)/arm9/source/ds_main.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/isomap.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+sound/rate.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/actor_walk.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/actor_path.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/image.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+sound/fmopl.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/scumm/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/m4/actor.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/scumm/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/cine/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/agos/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/gfx.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/saga/sprite.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/m4/sprite.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+engines/agi/sprite.o: CXXFLAGS:=$(CXXFLAGS) $(OPT_SPEED)
+# TODO: Fingolfin says: optimizing staticres 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 +139,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 +151,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 +175,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 +183,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..f6b69b3633 100644
--- a/backends/platform/ds/module.mk
+++ b/backends/platform/ds/module.mk
@@ -12,8 +12,6 @@ PORT_OBJS := \
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 +19,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 +26,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 +45,65 @@ 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/ \
+ backends/platform/ds/arm7/source/ \
+ backends/platform/ds/arm7/source/libcartreset/ \
+ backends/platform/ds/arm9/source/ \
+ backends/platform/ds/arm9/source/fat/
# We don't use the rules.mk here on purpose
OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)
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/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/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/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/psp/Makefile b/backends/platform/psp/Makefile
index 7f8bb63b0a..fed558eaad 100644
--- a/backends/platform/psp/Makefile
+++ b/backends/platform/psp/Makefile
@@ -124,17 +124,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,6 +147,7 @@ OBJS := powerman.o \
pspkeyboard.o \
audio.o \
thread.o \
+ rtc.o \
mp3.o
# Include common Scummvm makefile
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/display_manager.cpp b/backends/platform/psp/display_manager.cpp
index c2f21e084b..a9f33f6091 100644
--- a/backends/platform/psp/display_manager.cpp
+++ b/backends/platform/psp/display_manager.cpp
@@ -311,27 +311,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 +363,8 @@ void DisplayManager::renderAll() {
_keyboard->setClean();
_masterGuRenderer.guPostRender();
+
+ return true; // rendered successfully
}
inline bool DisplayManager::isTimeToUpdate() {
@@ -375,7 +379,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..dbbdf2022c 100644
--- a/backends/platform/psp/display_manager.h
+++ b/backends/platform/psp/display_manager.h
@@ -40,12 +40,12 @@ public:
void setupCallbackThread();
private:
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;
+ bool _renderFinished; // for sync with render callback
+ int _callbackId; // to keep track of render callback
};
class Screen;
@@ -68,7 +68,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 +83,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/module.mk b/backends/platform/psp/module.mk
index 99170ce7fb..e9c896acfd 100644
--- a/backends/platform/psp/module.mk
+++ b/backends/platform/psp/module.mk
@@ -15,6 +15,7 @@ MODULE_OBJS := powerman.o \
pspkeyboard.o \
audio.o \
thread.o \
+ rtc.o \
mp3.o
MODULE_DIRS += \
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..c26aed539e 100644
--- a/backends/platform/psp/psp_main.cpp
+++ b/backends/platform/psp/psp_main.cpp
@@ -110,12 +110,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 */
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/psp/rtc.h b/backends/platform/psp/rtc.h
new file mode 100644
index 0000000000..7c1a28474d
--- /dev/null
+++ b/backends/platform/psp/rtc.h
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * 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 $
+ *
+ */
+
+#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:
+ PspRtc()
+ : _startMillis(0), _startMicros(0),
+ _lastMillis(0), _milliOffset(0),
+ _looped(false) {
+ init();
+ }
+ void init();
+ uint32 getMillis();
+ uint32 getMicros();
+};
+
+#endif \ No newline at end of file
diff --git a/backends/platform/psp/thread.cpp b/backends/platform/psp/thread.cpp
index 4e7d5eada9..c19ff5f9e3 100644
--- a/backends/platform/psp/thread.cpp
+++ b/backends/platform/psp/thread.cpp
@@ -23,14 +23,13 @@
*
*/
-#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 PspThread --------------------------------------------------
+
void PspThread::delayMillis(uint32 ms) {
sceKernelDelayThread(ms * 1000);
}
@@ -39,49 +38,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 ((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;
- }
+ if (sceKernelReferSemaStatus((SceUID)_handle, &info) < 0)
+ PSP_ERROR("failed to retrieve semaphore info for handle %d\n", _handle);
+
+ return info.currentCount;
+}
+
+bool PspSemaphore::pollForValue(int value) {
+ DEBUG_ENTER_FUNC();
+ if (sceKernelPollSema((SceUID)_handle, value) < 0)
+ return false;
+
+ return true;
+}
+
+// false: timeout or error
+bool PspSemaphore::takeWithTimeOut(uint32 timeOut) {
+ DEBUG_ENTER_FUNC();
- _lastMillis = millis;
+ uint32 *pTimeOut = 0;
+ if (timeOut)
+ pTimeOut = &timeOut;
- return millis + _milliOffset;
+ if (sceKernelWaitSema(_handle, 1, pTimeOut) < 0) // we always wait for 1
+ return false;
+ return true;
}
-uint32 PspRtc::getMicros() {
- uint32 ticks[2];
+bool PspSemaphore::give(int num /*=1*/) {
+ DEBUG_ENTER_FUNC();
- sceRtcGetCurrentTick((u64 *)ticks);
- ticks[0] -= _startMicros;
+ 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 ticks[0];
+ if (_ownerId == threadId) {
+ _recursiveCount++;
+ } else {
+ ret = _semaphore.take();
+ _ownerId = threadId;
+ _recursiveCount = 0;
+ }
+ return ret;
+}
+
+bool PspMutex::unlock() {
+ DEBUG_ENTER_FUNC();
+ int threadId = sceKernelGetThreadId();
+ bool ret = true;
+
+ if (_ownerId != threadId) {
+ PSP_ERROR("attempt to unlock mutex by thread[%x] as opposed to owner[%x]\n",
+ threadId, _ownerId);
+ return false;
+ }
+
+ if (_recursiveCount) {
+ _recursiveCount--;
+ } else {
+ _ownerId = 0;
+ ret = _semaphore.give(1);
+ }
+ return ret;
+}
+
+// Class PspCondition -------------------------------------------------
+
+// Release all threads waiting on the condition
+void PspCondition::releaseAll() {
+ _mutex.lock();
+ if (_waitingThreads > _signaledThreads) { // we have signals to issue
+ int numWaiting = _waitingThreads - _signaledThreads; // threads we haven't signaled
+ _signaledThreads = _waitingThreads;
+
+ _waitSem.give(numWaiting);
+ _mutex.unlock();
+ for (int i=0; i<numWaiting; i++) // wait for threads to tell us they're awake
+ _doneSem.take();
+ } else {
+ _mutex.unlock();
+ }
+}
+
+// Mutex must be taken before entering wait
+void PspCondition::wait(PspMutex &externalMutex) {
+ _mutex.lock();
+ _waitingThreads++;
+ _mutex.unlock();
+
+ externalMutex.unlock(); // must unlock external mutex
+
+ _waitSem.take(); // sleep on the wait semaphore
+
+ // let the signaling thread know we're done
+ _mutex.lock();
+ if (_signaledThreads > 0 ) {
+ _doneSem.give(); // let the thread know
+ _signaledThreads--;
+ }
+ _waitingThreads--;
+ _mutex.unlock();
+
+ externalMutex.lock(); // must lock external mutex here for continuation
}
diff --git a/backends/platform/psp/thread.h b/backends/platform/psp/thread.h
index 380159fa2d..27d53903d6 100644
--- a/backends/platform/psp/thread.h
+++ b/backends/platform/psp/thread.h
@@ -34,18 +34,46 @@ public:
static void delayMicros(uint32 us);
};
-class PspRtc {
+class PspSemaphore {
private:
- uint32 _startMillis;
- uint32 _startMicros;
- uint32 _lastMillis;
- uint32 _milliOffset; // to prevent looping around of millis
- bool _looped; // make sure we only loop once
+ uint32 _handle;
public:
- PspRtc() : _startMillis(0), _startMicros(0), _lastMillis(0), _milliOffset(0), _looped(false) { init(); }
- void init();
- uint32 getMillis();
- uint32 getMicros();
+ PspSemaphore(int initialValue, int maxValue=255);
+ ~PspSemaphore();
+ bool take() { return takeWithTimeOut(0); }
+ bool takeWithTimeOut(uint32 timeOut);
+ bool give(int num=1);
+ bool pollForValue(int value); // check for a certain value
+ int numOfWaitingThreads();
+ int getValue();
+};
+
+class PspMutex {
+private:
+ PspSemaphore _semaphore;
+ int _recursiveCount;
+ int _ownerId;
+public:
+ PspMutex(bool initialValue) : _semaphore(initialValue ? 1 : 0, 255), _recursiveCount(0), _ownerId(0) {} // initial, max value
+ bool lock();
+ bool unlock();
+ bool poll() { return _semaphore.pollForValue(1); }
+ int numOfWaitingThreads() { return _semaphore.numOfWaitingThreads(); }
+ bool getValue() { return (bool)_semaphore.getValue(); }
+};
+
+class PspCondition {
+private:
+ PspMutex _mutex;
+ int _waitingThreads;
+ int _signaledThreads;
+ PspSemaphore _waitSem;
+ PspSemaphore _doneSem;
+public:
+ PspCondition() : _mutex(true), _waitingThreads(0), _signaledThreads(0),
+ _waitSem(0), _doneSem(0) {}
+ void wait(PspMutex &externalMutex);
+ void releaseAll();
};
enum ThreadPriority {
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..ade8fd7214 100644
--- a/backends/platform/psp/trace.h
+++ b/backends/platform/psp/trace.h
@@ -39,8 +39,8 @@
#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 +52,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/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/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/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..e795b82d0a 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
@@ -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")
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 7f3b9467b3..477f2afcb1 100644
--- a/base/main.cpp
+++ b/base/main.cpp
@@ -47,11 +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/mididrv.h"
+
#include "backends/keymapper/keymapper.h"
#if defined(_WIN32_WCE)
@@ -100,7 +103,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) {
@@ -139,7 +142,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(),
@@ -198,7 +201,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
@@ -266,22 +269,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);
@@ -317,6 +320,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
@@ -336,6 +341,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;
@@ -385,7 +400,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
@@ -411,8 +426,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"));
}
// reset the graphics to default
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 6c80da65d4..a6acd7e449 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -167,6 +167,7 @@ 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)
@@ -174,7 +175,7 @@ public:
#if defined(UNIX) && defined(USE_ALSA)
LINK_PLUGIN(ALSA)
#endif
- #if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__)
+ #if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__) && !defined(__ANDROID__)
LINK_PLUGIN(SEQ)
#endif
#if defined(__MINT__)
@@ -204,6 +205,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/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/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..fe87b5f642
--- /dev/null
+++ b/common/messages.cpp
@@ -0,0 +1,2063 @@
+// 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 Device:",
+ /* 128 */ "MT-32 Emulator",
+ /* 129 */ "Main screen scaling:",
+ /* 130 */ "Map",
+ /* 131 */ "Mass Add...",
+ /* 132 */ "Menu",
+ /* 133 */ "Misc",
+ /* 134 */ "Mixed AdLib/MIDI mode",
+ /* 135 */ "Mount DVD",
+ /* 136 */ "Mount SMB",
+ /* 137 */ "Mouse click",
+ /* 138 */ "Multi Function",
+ /* 139 */ "Music Device:",
+ /* 140 */ "Music volume:",
+ /* 141 */ "Mute All",
+ /* 142 */ "Name:",
+ /* 143 */ "Network down",
+ /* 144 */ "Network not initialsed (%d)",
+ /* 145 */ "Network up",
+ /* 146 */ "Network up, share mounted",
+ /* 147 */ "Never",
+ /* 148 */ "No",
+ /* 149 */ "No date saved",
+ /* 150 */ "No music",
+ /* 151 */ "No playtime saved",
+ /* 152 */ "No time saved",
+ /* 153 */ "None",
+ /* 154 */ "Normal (no scaling)",
+ /* 155 */ "OK",
+ /* 156 */ "Output rate:",
+ /* 157 */ "Override global MIDI settings",
+ /* 158 */ "Override global audio settings",
+ /* 159 */ "Override global graphic settings",
+ /* 160 */ "Override global volume settings",
+ /* 161 */ "PC Speaker Emulator",
+ /* 162 */ "Password:",
+ /* 163 */ "Path not a directory",
+ /* 164 */ "Path not a file",
+ /* 165 */ "Path not exists",
+ /* 166 */ "Paths",
+ /* 167 */ "Pause",
+ /* 168 */ "Pick the game:",
+ /* 169 */ "Platform the game was originally designed for",
+ /* 170 */ "Platform:",
+ /* 171 */ "Playtime: ",
+ /* 172 */ "Please select an action",
+ /* 173 */ "Plugins Path:",
+ /* 174 */ "Preferred Device:",
+ /* 175 */ "Press the key to associate",
+ /* 176 */ "Quit",
+ /* 177 */ "Quit ScummVM",
+ /* 178 */ "Read permission denied",
+ /* 179 */ "Reading failed",
+ /* 180 */ "Remap keys",
+ /* 181 */ "Remove game from the list. The game data files stay intact",
+ /* 182 */ "Render mode:",
+ /* 183 */ "Right",
+ /* 184 */ "Right Click",
+ /* 185 */ "Right click",
+ /* 186 */ "Rotate",
+ /* 187 */ "SFX volume:",
+ /* 188 */ "SMB",
+ /* 189 */ "Save",
+ /* 190 */ "Save Path:",
+ /* 191 */ "Save Path: ",
+ /* 192 */ "Save game:",
+ /* 193 */ "Scan complete!",
+ /* 194 */ "Scanned %d directories ...",
+ /* 195 */ "ScummVM Main Menu",
+ /* 196 */ "ScummVM could not find any engine capable of running the selected game!",
+ /* 197 */ "ScummVM could not find any game in the specified directory!",
+ /* 198 */ "ScummVM couldn't open the specified directory!",
+ /* 199 */ "Search in game list",
+ /* 200 */ "Search:",
+ /* 201 */ "Select SoundFont",
+ /* 202 */ "Select a Theme",
+ /* 203 */ "Select additional game directory",
+ /* 204 */ "Select an action and click 'Map'",
+ /* 205 */ "Select directory for GUI themes",
+ /* 206 */ "Select directory for extra files",
+ /* 207 */ "Select directory for plugins",
+ /* 208 */ "Select directory for saved games",
+ /* 209 */ "Select directory for savegames",
+ /* 210 */ "Select directory with game data",
+ /* 211 */ "Sensitivity",
+ /* 212 */ "Server:",
+ /* 213 */ "Share:",
+ /* 214 */ "Short game identifier used for referring to savegames and running the game from the command line",
+ /* 215 */ "Show Keyboard",
+ /* 216 */ "Show mouse cursor",
+ /* 217 */ "Show subtitles and play speech",
+ /* 218 */ "Show/Hide Cursor",
+ /* 219 */ "Skip",
+ /* 220 */ "Skip line",
+ /* 221 */ "Skip text",
+ /* 222 */ "Snap to edges",
+ /* 223 */ "Software scale (good quality, but slower)",
+ /* 224 */ "Sound on/off",
+ /* 225 */ "SoundFont is supported by some audio cards, Fluidsynth and Timidity",
+ /* 226 */ "SoundFont:",
+ /* 227 */ "Spch",
+ /* 228 */ "Special dithering modes supported by some games",
+ /* 229 */ "Special sound effects volume",
+ /* 230 */ "Specifies default sound device for General MIDI output",
+ /* 231 */ "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output",
+ /* 232 */ "Specifies output sound device or sound card emulator",
+ /* 233 */ "Specifies path to additional data used by all games or ScummVM",
+ /* 234 */ "Specifies path to additional data used the game",
+ /* 235 */ "Specifies preferred sound device or sound card emulator",
+ /* 236 */ "Specifies where your savegames are put",
+ /* 237 */ "Speech",
+ /* 238 */ "Speech volume:",
+ /* 239 */ "Standard Renderer (16bpp)",
+ /* 240 */ "Start selected game",
+ /* 241 */ "Status:",
+ /* 242 */ "Subs",
+ /* 243 */ "Subtitle speed:",
+ /* 244 */ "Subtitles",
+ /* 245 */ "Swap character",
+ /* 246 */ "Tap for left click, double tap right click",
+ /* 247 */ "Text and Speech:",
+ /* 248 */ "The chosen directory cannot be written to. Please select another one.",
+ /* 249 */ "Theme Path:",
+ /* 250 */ "Theme:",
+ /* 251 */ "This game ID is already taken. Please choose another one.",
+ /* 252 */ "This game does not support loading games from the launcher.",
+ /* 253 */ "Time: ",
+ /* 254 */ "Timeout while initialising network",
+ /* 255 */ "Touch X Offset",
+ /* 256 */ "Touch Y Offset",
+ /* 257 */ "Touchpad mode disabled.",
+ /* 258 */ "Touchpad mode enabled.",
+ /* 259 */ "True Roland MT-32 (disable GM emulation)",
+ /* 260 */ "Turns off General MIDI mapping for games with Roland MT-32 soundtrack",
+ /* 261 */ "Unknown",
+ /* 262 */ "Unknown Error",
+ /* 263 */ "Unmount DVD",
+ /* 264 */ "Unmount SMB",
+ /* 265 */ "Unscaled (you must scroll left and right)",
+ /* 266 */ "Unsupported Color Mode",
+ /* 267 */ "Untitled savestate",
+ /* 268 */ "Up",
+ /* 269 */ "Use both MIDI and AdLib sound generation",
+ /* 270 */ "Use laptop trackpad-style cursor control",
+ /* 271 */ "Username:",
+ /* 272 */ "Using SDL driver ",
+ /* 273 */ "Vertical underscan:",
+ /* 274 */ "Video",
+ /* 275 */ "Virtual keyboard",
+ /* 276 */ "Volume",
+ /* 277 */ "Windows MIDI",
+ /* 278 */ "Write permission denied",
+ /* 279 */ "Writing data failed",
+ /* 280 */ "Yes",
+ /* 281 */ "You have to restart ScummVM to take the effect.",
+ /* 282 */ "Zone",
+ /* 283 */ "Zoom down",
+ /* 284 */ "Zoom up",
+ /* 285 */ "every 10 mins",
+ /* 286 */ "every 15 mins",
+ /* 287 */ "every 30 mins",
+ /* 288 */ "every 5 mins",
+ /* 289 */ "~A~bout",
+ /* 290 */ "~A~dd Game...",
+ /* 291 */ "~C~ancel",
+ /* 292 */ "~C~lose",
+ /* 293 */ "~E~dit Game...",
+ /* 294 */ "~H~elp",
+ /* 295 */ "~I~ndy fight controls",
+ /* 296 */ "~K~eys",
+ /* 297 */ "~L~eft handed mode",
+ /* 298 */ "~L~oad",
+ /* 299 */ "~L~oad...",
+ /* 300 */ "~N~ext",
+ /* 301 */ "~O~K",
+ /* 302 */ "~O~ptions",
+ /* 303 */ "~O~ptions...",
+ /* 304 */ "~P~revious",
+ /* 305 */ "~Q~uit",
+ /* 306 */ "~R~emove Game",
+ /* 307 */ "~R~esume",
+ /* 308 */ "~R~eturn to Launcher",
+ /* 309 */ "~S~ave",
+ /* 310 */ "~S~tart",
+ /* 311 */ "~T~ransitions Enabled",
+ /* 312 */ "~W~ater Effect Enabled",
+ /* 313 */ "~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-12 17:44+0200\nPO-Revision-Date: 2010-06-13 20:55+0300\nLast-Translator: Eugene Sandulenko <sev@scummvm.org>\nLanguage-Team: Russian\nLanguage: \nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-5\nContent-Transfer-Encoding: 8bit\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. \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\320\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\342\341\322\336 GM:" },
+ { 85, "\317\327\353\332 \330\335\342\325\340\344\325\331\341\320:" },
+ { 86, "\300\320\341\342\325\340\330\327\320\342\336\340 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, "\277\343\342\354 \332 \330\323\340\325: " },
+ { 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\330\347\325\341\332\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\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, "\303\341\342\340\336\331\341\342\322\336 MT32:" },
+ { 128, "\315\334\343\333\357\342\336\340 MT-32" },
+ { 129, "\274\320\341\350\342\320\321 \323\333\320\322\335\336\323\336 \355\332\340\320\335\320:" },
+ { 130, "\275\320\327\335\320\347\330\342\354" },
+ { 131, "\264\336\321. \334\335\336\323\336..." },
+ { 132, "\274\325\335\356" },
+ { 133, "\300\320\327\335\336\325" },
+ { 134, "\301\334\325\350\320\335\335\353\331 \340\325\326\330\334 AdLib/MIDI" },
+ { 135, "\277\336\324\332\333\356\347\330\342\354 DVD" },
+ { 136, "\277\336\324\332\333\356\347\330\342\354 SMB" },
+ { 137, "\272\333\330\332 \334\353\350\354\356" },
+ { 138, "\274\343\333\354\342\330\344\343\335\332\346\330\357" },
+ { 139, "\303\341\342\340\336\331\342\341\322\336 GM:" },
+ { 140, "\263\340\336\334\332\336\341\342\354 \334\343\327\353\332\330:" },
+ { 141, "\262\353\332\333\356\347\330\342\354 \322\341\361" },
+ { 142, "\275\320\327\322\320\335\330\325:" },
+ { 143, "\301\325\342\354 \322\353\332\333\356\347\325\335\320" },
+ { 144, "\301\325\342\354 \335\325 \335\320\341\342\340\336\325\335\320 (%d)" },
+ { 145, "\301\325\342\354 \340\320\321\336\342\320\325\342" },
+ { 146, "\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" },
+ { 147, "\275\330\332\336\323\324\320" },
+ { 148, "\275\325\342" },
+ { 149, "\264\320\342\320 \335\325 \327\320\337\330\341\320\335\320" },
+ { 150, "\261\325\327 \334\343\327\353\332\330" },
+ { 151, "\262\340\325\334\357 \330\323\340\353 \335\325 \327\320\337\330\341\320\335\336" },
+ { 152, "\262\340\325\334\357 \335\325 \327\320\337\330\341\320\335\336" },
+ { 153, "\275\325 \327\320\324\320\335" },
+ { 154, "\261\325\327 \343\322\325\333\330\347\325\335\330\357" },
+ { 155, "OK" },
+ { 156, "\262\353\345\336\324\335\320\357 \347\320\341\342\336\342\320:" },
+ { 157, "\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" },
+ { 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 \320\343\324\330\336" },
+ { 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 \323\340\320\344\330\332\330" },
+ { 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 \323\340\336\334\332\336\341\342\330" },
+ { 161, "\315\334\343\333\357\342\336\340 PC \341\337\330\332\325\340\320" },
+ { 162, "\277\320\340\336\333\354:" },
+ { 163, "\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" },
+ { 164, "\277\343\342\354 \335\325 \357\322\333\357\325\342\341\357 \344\320\331\333\336\334" },
+ { 165, "\277\343\342\354 \335\325 \335\320\331\324\325\335" },
+ { 166, "\277\343\342\330" },
+ { 167, "\277\320\343\327\320" },
+ { 168, "\262\353\321\325\340\330\342\325 \330\323\340\343:" },
+ { 169, "\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" },
+ { 170, "\277\333\320\342\344\336\340\334\320:" },
+ { 171, "\262\340\325\334\357 \330\323\340\353: " },
+ { 172, "\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" },
+ { 173, "\277\343\342\354 \332 \337\333\320\323\330\335\320\334:" },
+ { 174, "\277\340\325\324\337\336\347\330\342\320\325\334\336\325 \343\341\342\340\336\331\341\342\322\336:" },
+ { 175, "\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" },
+ { 176, "\262\353\345\336\324" },
+ { 177, "\262\353\345\336\324 \330\327 ScummVM" },
+ { 178, "\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" },
+ { 179, "\276\350\330\321\332\320 \347\342\325\335\330\357" },
+ { 180, "\277\325\340\325\335\320\327\335\320\347\330\342\354 \332\333\320\322\330\350\330" },
+ { 181, "\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" },
+ { 182, "\300\325\326\330\334 \340\320\341\342\340\330\340\336\322\320\335\330\357:" },
+ { 183, "\262\337\340\320\322\336" },
+ { 184, "\277\340\320\322\353\331 \351\325\333\347\336\332" },
+ { 185, "\277\340\320\322\353\331 \351\325\333\347\336\332" },
+ { 186, "\277\336\322\325\340\335\343\342\354" },
+ { 187, "\263\340\336\334\332\336\341\342\354 \355\344\344\325\332\342\336\322:" },
+ { 188, "SMB" },
+ { 189, "\267\320\337\330\341\320\342\354" },
+ { 190, "\277\343\342\354 \341\336\345\340.: " },
+ { 191, "\277\343\342\354 \324\333\357 \341\336\345\340\320\335\325\335\330\331: " },
+ { 192, "\301\336\345\340\320\335\330\342\354 \330\323\340\343: " },
+ { 193, "\277\336\330\341\332 \327\320\332\336\335\347\325\335!" },
+ { 194, "\277\340\336\341\334\336\342\340\325\335\336 %d \324\330\340\325\332\342\336\340\330\331 ..." },
+ { 195, "\263\333\320\322\335\336\325 \334\325\335\356 ScummVM" },
+ { 196, "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!" },
+ { 197, "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!" },
+ { 198, "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!" },
+ { 199, "\277\336\330\341\332 \322 \341\337\330\341\332\325 \330\323\340" },
+ { 200, "\277\336\330\341\332:" },
+ { 201, "\262\353\321\325\340\330\342\325 SoundFont" },
+ { 202, "\262\353\321\325\340\330\342\325 \342\325\334\343" },
+ { 203, "\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" },
+ { 204, "\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'" },
+ { 205, "\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" },
+ { 206, "\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" },
+ { 207, "\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" },
+ { 208, "\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" },
+ { 209, "\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" },
+ { 210, "\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" },
+ { 211, "\307\343\322\341\342\322\330\342\325\333\354\335\336\341\342\354" },
+ { 212, "\301\325\340\322\325\340:" },
+ { 213, "\301\325\342\325\322\320\357 \337\320\337\332\320:" },
+ { 214, "\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" },
+ { 215, "\277\336\332\320\327\320\342\354 \332\333\320\322\330\320\342\343\340\343" },
+ { 216, "\277\336\332\320\327\353\322\320\342\354 \332\343\340\341\336\340 \334\353\350\330" },
+ { 217, "\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" },
+ { 218, "\277\336\332\320\327\320\342\354/\303\321\340\320\342\354 \332\343\340\341\336\340" },
+ { 219, "\277\340\336\337\343\341\342\330\342\354" },
+ { 220, "\277\340\336\337\343\341\342\330\342\354 \341\342\340\336\332\343" },
+ { 221, "\277\340\336\337\343\341\342\330\342\354 \342\325\332\341\342" },
+ { 222, "\277\340\330\332\340\325\337\330\342\354 \332 \323\340\320\335\330\346\320\334" },
+ { 223, "\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)" },
+ { 224, "\267\322\343\332 \322\332\333/\322\353\332\333" },
+ { 225, "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" },
+ { 226, "SoundFont:" },
+ { 227, "\276\327\322" },
+ { 228, "\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" },
+ { 229, "\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" },
+ { 230, "\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" },
+ { 231, "\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" },
+ { 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 \330\333\330 \355\334\343\333\357\342\336\340 \327\322\343\332\336\322\336\331 \332\320\340\342\353" },
+ { 233, "\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" },
+ { 234, "\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" },
+ { 235, "\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" },
+ { 236, "\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" },
+ { 237, "\276\327\322\343\347\332\320" },
+ { 238, "\263\340\336\334\332\336\341\342\354 \336\327\322\343\347\332\330:" },
+ { 239, "\301\342\320\335\324\320\340\342\335\353\331 \340\320\341\342\325\340\330\327\320\342\336\340 (16bpp)" },
+ { 240, "\267\320\337\343\341\342\330\342\354 \322\353\321\340\320\335\335\343\356 \330\323\340\343" },
+ { 241, "\301\336\341\342\336\357\335\330\325:" },
+ { 242, "\301\343\321" },
+ { 243, "\301\332\336\340\336\341\342\354 \341\343\321\342\330\342\340\336\322:" },
+ { 244, "\301\343\321\342\330\342\340\353" },
+ { 245, "\301\334\325\335\330\342\354 \323\325\340\336\357" },
+ { 246, "\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" },
+ { 247, "\302\325\332\341\342 \330 \336\327\322\343\347\332\320:" },
+ { 248, "\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." },
+ { 249, "\277\343\342\354 \332 \342\325\334\320\334:" },
+ { 250, "\302\325\334\320:" },
+ { 251, "\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." },
+ { 252, "\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." },
+ { 253, "\262\340\325\334\357: " },
+ { 254, "\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" },
+ { 255, "\301\334\325\351\325\335\330\325 \332\320\341\320\335\330\331 \337\336 \336\341\330 X" },
+ { 256, "\301\334\325\351\325\335\330\325 \332\320\341\320\335\330\331 \337\336 \336\341\330 Y" },
+ { 257, "\300\325\326\330\334 \342\320\347\337\320\324\320 \322\353\332\333\356\347\325\335." },
+ { 258, "\300\325\326\330\334 \342\320\347\337\320\324\320 \322\332\333\356\347\325\335." },
+ { 259, "\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)" },
+ { 260, "\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" },
+ { 261, "\275\325\330\327\322\325\341\342\335\336" },
+ { 262, "\275\325\330\327\322\325\341\342\335\320\357 \336\350\330\321\332\320" },
+ { 263, "\276\342\332\333\356\347\330\342\354 DVD" },
+ { 264, "\276\342\332\333\356\347\342\354 SMB" },
+ { 265, "\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)" },
+ { 266, "\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" },
+ { 267, "\301\336\345\340\320\335\325\335\330\325 \321\325\327 \330\334\325\335\330" },
+ { 268, "\262\322\325\340\345" },
+ { 269, "\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" },
+ { 270, "\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" },
+ { 271, "\277\336\333\354\327\336\322\320\342\325\333\354:" },
+ { 272, "\270\341\337\336\333\354\327\343\356 \324\340\320\331\322\325\340 SDL " },
+ { 273, "\262\325\340\342\330\332\320\333\354\335\353\331 underscan:" },
+ { 274, "\262\330\324\325\336" },
+ { 275, "\262\330\340\342\343\320\333\354\335\320\357 \332\333\320\322\330\320\342\343\340\320" },
+ { 276, "\263\340\336\334\332\336\341\342\354" },
+ { 277, "Windows MIDI" },
+ { 278, "\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" },
+ { 279, "\276\350\330\321\332\320 \327\320\337\330\341\330 \324\320\335\335\353\345" },
+ { 280, "\264\320" },
+ { 281, "\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." },
+ { 282, "\267\336\335\320" },
+ { 283, "\303\334\325\335\354\350. \334\320\341\350\342\320\321" },
+ { 284, "\303\322\325\333. \334\320\341\350\342\320\321" },
+ { 285, "\332\320\326\324\353\325 10 \334\330\335\343\342" },
+ { 286, "\332\320\326\324\353\325 15 \334\330\335\343\342" },
+ { 287, "\332\320\326\324\353\325 30 \334\330\335\343\342" },
+ { 288, "\332\320\326\324\353\325 5 \334\330\335\343\342" },
+ { 289, "\276 \337\340\336~\323~\340\320\334\334\325" },
+ { 290, "~\264~\336\321. \330\323\340\343..." },
+ { 291, "\276~\342~\334\325\335\320" },
+ { 292, "~\267~\320\332\340\353\342\354" },
+ { 293, "\270\327~\334~. \330\323\340\343..." },
+ { 294, "~\277~\336\334\336\351\354" },
+ { 295, "\303\337\340\320\322\333\325\335\330\325 \321\336\357\334\330 \322 Indy" },
+ { 296, "~\272~\333\320\322\330\350\330" },
+ { 297, "\273\325\322\336\340\343\332\330\331 \340\325\326\330\334" },
+ { 298, "~\267~\320\323\340\343\327\330\342\354" },
+ { 299, "~\267~\320\323\340...." },
+ { 300, "~\301~\333\325\324" },
+ { 301, "~O~K" },
+ { 302, "~\276~\337\346\330\330" },
+ { 303, "~\276~\337\346\330\330..." },
+ { 304, "~\277~\340\325\324" },
+ { 305, "~\262~\353\345\336\324" },
+ { 306, "~\303~\324\320\333\330\342\354 \330\323\340\343" },
+ { 307, "\277\340\336\324\336\333~\326~\330\342\354" },
+ { 308, "~\262~\325\340\335\343\342\354\341\357 \322 \323\333\320\322\335\336\325 \334\325\335\356" },
+ { 309, "~\267~\320\337\330\341\320\342\354" },
+ { 310, "\277~\343~\341\332" },
+ { 311, "\277\325\340\325\345\336\324\353 \320\332\342\330\322\330\340\336\322\320\335\353" },
+ { 312, "\315\344\344\325\332\342\353 \322\336\324\353 \322\332\333\356\347\325\335\353" },
+ { 313, "\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_fr_FR[] = {
+ { 0, "Project-Id-Version: ScummVM 1.2.0svn\nReport-Msgid-Bugs-To: scummvm-devel@lists.sf.net\nPOT-Creation-Date: 2010-07-12 17:44+0200\nPO-Revision-Date: 2010-07-09 18:17+0100\nLast-Translator: Thierry Crozat <criezy@scummvm.org>\nLanguage-Team: French <scummvm-devel@lists.sf.net>\nLanguage: Francais\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\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, "Sortie MT-32:" },
+ { 128, "\311mulateur MT-32" },
+ { 129, "\311chelle de l'\351cran principal" },
+ { 130, "Affecter" },
+ { 131, "Ajout Massif..." },
+ { 132, "Menu" },
+ { 133, "Divers" },
+ { 134, "Mode mixe AdLib/MIDI" },
+ { 135, "Monter le DVD" },
+ { 136, "Monter SMB" },
+ { 137, "Clic de souris" },
+ { 138, "Fonction Multiple" },
+ { 139, "Sortie Audio:" },
+ { 140, "Volume Musique:" },
+ { 141, "Silence" },
+ { 142, "Nom:" },
+ { 143, "R\351seau d\351connect\351" },
+ { 144, "R\351seau non initialis\351 (%d)" },
+ { 145, "R\351seau connect\351" },
+ { 146, "R\351seau connect\351, disque partag\351 mont\351" },
+ { 147, "Jamais" },
+ { 148, "Non" },
+ { 149, "Date non sauv\351e" },
+ { 150, "Pas de musique" },
+ { 151, "Dur\351e de jeu non sauv\351e" },
+ { 152, "Heure non sauv\351e" },
+ { 153, "Aucun" },
+ { 154, "Normal (\351chelle d'origine)" },
+ { 155, "OK" },
+ { 156, "Fr\351quence:" },
+ { 157, "Utiliser des r\351glages MIDI sp\351cifiques \340 ce jeux" },
+ { 158, "Utiliser des r\351glages audio sp\351cifiques \340 ce jeux" },
+ { 159, "Utiliser des r\351glages graphiques sp\351cifiques \340 ce jeux" },
+ { 160, "Utiliser des r\351glages de volume sonore sp\351cifiques \340 ce jeux" },
+ { 161, "\311mulateur Haut Parleur PC" },
+ { 162, "Mot de passe:" },
+ { 163, "Chemin n'est pas un r\351pertoire" },
+ { 164, "Chemin n'est pas un fichier" },
+ { 165, "Chemin inexistant" },
+ { 166, "Chemins" },
+ { 167, "Mettre en pause" },
+ { 168, "Choisissez le jeu:" },
+ { 169, "Plateforme pour laquelle votre jeu a \351t\351 con\347u" },
+ { 170, "Plateforme:" },
+ { 171, "Dur\351e de jeu:" },
+ { 172, "Selectionnez une action" },
+ { 173, "Plugins:" },
+ { 174, "Sortie Pr\351f\351r\351:" },
+ { 175, "Appuyez sur la touche \340 associer" },
+ { 176, "Quitter" },
+ { 177, "Quitter ScummVM" },
+ { 178, "V\351roulli\351 en lecture" },
+ { 179, "Echec de la lecture" },
+ { 180, "Changer l'affectation des touches" },
+ { 181, "Supprime le jeu de la liste. Les fichiers sont conserv\351s" },
+ { 182, "Mode de rendu:" },
+ { 183, "Droite" },
+ { 184, "Clic Droit" },
+ { 185, "Clic droit" },
+ { 186, "Pivoter" },
+ { 187, "Volume Bruitage:" },
+ { 188, "SMB" },
+ { 189, "Sauver" },
+ { 190, "Sauvegardes:" },
+ { 191, "Sauvegardes:" },
+ { 192, "Sauvegarde:" },
+ { 193, "Examen termin\351!" },
+ { 194, "%d r\351pertoires examin\351s ..." },
+ { 195, "Menu Principal ScummVM" },
+ { 196, "ScummVM n'a pas pu trouv\351 de moteur pour lancer le jeu s\351lectionn\351." },
+ { 197, "ScummVM n'a pas trouv\351 de jeux dans le r\351pertoire s\351lectionn\351." },
+ { 198, "ScummVM n'a pas pu ouvrir le r\351pertoire s\351lectionn\351." },
+ { 199, "Recherche dans la liste de jeux" },
+ { 200, "Filtre:" },
+ { 201, "Choisir une banque de sons" },
+ { 202, "S\351lectionnez un Th\350me" },
+ { 203, "S\351lectionner un r\351pertoire suppl\351mentaire" },
+ { 204, "Selectionez une action et cliquez 'Affecter'" },
+ { 205, "S\351lectionner le r\351pertoire des th\350mes d'interface" },
+ { 206, "S\351lectionner le r\351pertoire pour les fichiers supl\351mentaires" },
+ { 207, "S\351lectionner le r\351pertoire des plugins" },
+ { 208, "S\351lectionner le r\351pertoire pour les sauvegardes" },
+ { 209, "S\351lectionner le r\351pertoire pour les sauvegardes" },
+ { 210, "S\351lectionner le r\351pertoire contenant les donn\351es du jeu" },
+ { 211, "Sensibilit\351" },
+ { 212, "Serveur:" },
+ { 213, "Disque partag\351:" },
+ { 214, "ID compact du jeu utilis\351 pour identifier les sauvegardes et d\351marrer le jeu depuis la ligne de commande" },
+ { 215, "Afficher le clavier" },
+ { 216, "Afficher le curseur de la souris" },
+ { 217, "Affiche les sous-titres et joue les dialogues audio" },
+ { 218, "Afficher/Cacher le curseur" },
+ { 219, "Passer" },
+ { 220, "Passer la phrase" },
+ { 221, "Sauter le texte" },
+ { 222, "Aligner sur les bords" },
+ { 223, "Mise \340 l'\351chelle logicielle (bonne qualit\351 mais plus lent)" },
+ { 224, "Audio marche/arr\352t" },
+ { 225, "La banque de sons est utilis\351e par certaines cartes audio, Fluidsynth et Timidity" },
+ { 226, "Banque de sons:" },
+ { 227, "Audio" },
+ { 228, "Mode sp\351cial de tramage support\351 par certains jeux" },
+ { 229, "Volume des effets sp\351ciaux sonores" },
+ { 230, "Sp\351cifie le p\351riph\351rique audio par d\351faut pour la sortie General MIDI" },
+ { 231, "Sp\351cifie le p\351riph\351rique audio par d\351faut pour la sortie Roland MT-32/LAPC1/CM32l/CM64" },
+ { 232, "Sp\351cifie le p\351riph\351rique de sortie audio ou l'\351mulateur de carte audio" },
+ { 233, "Sp\351cifie un chemin vers des donn\351es suppl\351mentaires utilis\351es par tous les jeux ou ScummVM" },
+ { 234, "D\351finie un chemin vers des donn\351es supl\351mentaires utilis\351es par le jeu" },
+ { 235, "Sp\351cifie le p\351riph\351rique de sortie audio ou l'\351mulateur de carte audio pr\351f\351r\351" },
+ { 236, "D\351finie l'emplacement o\371 les fichiers de sauvegarde sont cr\351\351s" },
+ { 237, "Audio" },
+ { 238, "Volume Dialogues:" },
+ { 239, "Standard (16bpp)" },
+ { 240, "D\351marre le jeu s\351lectionn\351" },
+ { 241, "Status:" },
+ { 242, "Subs" },
+ { 243, "Vitesse des ST:" },
+ { 244, "Sous-titres" },
+ { 245, "Changement de personnage" },
+ { 246, "Toucher pour un clic gauche, toucher deux fois pour un clic droit" },
+ { 247, "Dialogue:" },
+ { 248, "Le r\351pertoire s\351lectionn\351 est v\351rouill\351 en \351criture. S\351lectionnez un autre r\351pertoire." },
+ { 249, "Th\350mes:" },
+ { 250, "Th\350me:" },
+ { 251, "Cet ID est d\351j\340 utilis\351 par un autre jeu. Choisissez en un autre svp." },
+ { 252, "Le chargement de sauvegarde depuis le lanceur n'est pas support\351 pour ce jeu." },
+ { 253, "Heure:" },
+ { 254, "D\351passement du d\351lai lors de l'initialisation du r\351seau" },
+ { 255, "D\351calage X du toucher" },
+ { 256, "D\351callage Y du toucher" },
+ { 257, "Mode touchpad d\351sactiv\351" },
+ { 258, "Mode touchpad activ\351" },
+ { 259, "Roland MT-32 exacte (d\351sactive l'\351mulation GM)" },
+ { 260, "D\351sactiver la conversion des pistes MT-32 en General MIDI" },
+ { 261, "Inconue" },
+ { 262, "Erreur inconnue" },
+ { 263, "D\351monter le DVD" },
+ { 264, "D\351monter SMB" },
+ { 265, "Sans changement d'\351chelle (vous devez faire d\351filer l'\351cran)" },
+ { 266, "Mode de couleurs non support\351" },
+ { 267, "Sauvegarde sans nom" },
+ { 268, "Haut" },
+ { 269, "Utiliser \340 la fois MIDI et AdLib" },
+ { 270, "Activer le contr\364le du curseur de type trackpad" },
+ { 271, "Nom d'utilisateur:" },
+ { 272, "Utilise le pilote SDL" },
+ { 273, "Underscan vertical:" },
+ { 274, "Vid\351o" },
+ { 275, "Clavier virtuel" },
+ { 276, "Volume" },
+ { 277, "MIDI Windows" },
+ { 278, "Verrouill\351 en \351criture" },
+ { 279, "Echec de l'\351criture des donn\351es" },
+ { 280, "Oui" },
+ { 281, "Vous devez relancer ScummVM pour que le changement soit pris en compte." },
+ { 282, "Zone" },
+ { 283, "Zoomer" },
+ { 284, "D\351zoomer" },
+ { 285, "Toutes les 10 mins" },
+ { 286, "Toutes les 15 mins" },
+ { 287, "Toutes les 30 mins" },
+ { 288, "Toutes les 5 mins" },
+ { 289, "\300 ~P~ropos" },
+ { 290, "~A~jouter..." },
+ { 291, "~A~nnuler" },
+ { 292, "~F~ermer" },
+ { 293, "~E~diter..." },
+ { 294, "~A~ide" },
+ { 295, "Contr\364le des combats d'~I~ndy" },
+ { 296, "~T~ouches" },
+ { 297, "Mode ~G~aucher" },
+ { 298, "~C~harger" },
+ { 299, "~C~harger" },
+ { 300, "~S~uivant" },
+ { 301, "~O~K" },
+ { 302, "~O~ptions" },
+ { 303, "~O~ptions..." },
+ { 304, "~P~r\351c\351dent" },
+ { 305, "~Q~uitter" },
+ { 306, "~S~upprimer" },
+ { 307, "~R~eprendre" },
+ { 308, "Retour au ~L~anceur" },
+ { 309, "~S~auver" },
+ { 310, "~D~\351marrer" },
+ { 311, "T~r~ansitions activ\351" },
+ { 312, "~E~ffets de l'Eau Activ\351s" },
+ { 313, "Mode ~Z~ip Activ\351" },
+ { -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-12 17:44+0200\nPO-Revision-Date: 2010-06-30 23:56+0100\nLast-Translator: Maff <matteo.maff at gmail dot com>\nLanguage-Team: Italian\nLanguage: Italiano\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\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:" },
+ { 127, "Disposit. MT32:" },
+ { 128, "Emulatore MT-32" },
+ { 129, "Schermo principale:" },
+ { 130, "Mappa" },
+ { 131, "Agg. in massa..." },
+ { 132, "Menu" },
+ { 133, "Varie" },
+ { 134, "Modalit\340 mista AdLib/MIDI" },
+ { 135, "Monta DVD" },
+ { 136, "Monta SMB" },
+ { 137, "Clic del mouse" },
+ { 138, "Multifunzione" },
+ { 139, "Dispositivo GM:" },
+ { 140, "Volume musica:" },
+ { 141, "Disattiva audio" },
+ { 142, "Nome:" },
+ { 143, "Rete disattivata" },
+ { 144, "Rete non avviata (%d)" },
+ { 145, "Rete attiva" },
+ { 146, "Rete attiva, condivisione montata" },
+ { 147, "Mai" },
+ { 148, "No" },
+ { 149, "Nessuna data salvata" },
+ { 150, "Nessuna musica" },
+ { 151, "Nessun tempo salvato" },
+ { 152, "Nessun orario salvato" },
+ { 153, "Nessuno" },
+ { 154, "Normale (nessun ridimensionamento)" },
+ { 155, "OK" },
+ { 156, "Frequenza:" },
+ { 157, "Ignora le impostazioni MIDI globali" },
+ { 158, "Ignora le impostazioni audio globali" },
+ { 159, "Ignora le impostazioni grafiche globali" },
+ { 160, "Ignora le impostazioni globali di volume" },
+ { 161, "Emulatore PC Speaker" },
+ { 162, "Password:" },
+ { 163, "Il percorso non \350 una cartella" },
+ { 164, "Il percorso non \350 un file" },
+ { 165, "Il percorso non esiste" },
+ { 166, "Percorsi" },
+ { 167, "Pausa" },
+ { 168, "Scegli il gioco:" },
+ { 169, "La piattaforma per la quale il gioco \350 stato concepito" },
+ { 170, "Piattaforma:" },
+ { 171, "Tempo di gioco: " },
+ { 172, "Seleziona un'azione" },
+ { 173, "Percorso plugin:" },
+ { 174, "Disp. preferito:" },
+ { 175, "Premi il tasto da associare" },
+ { 176, "Esci" },
+ { 177, "Chiudi ScummVM" },
+ { 178, "Autorizzazione di lettura negata" },
+ { 179, "Lettura fallita" },
+ { 180, "Riprogramma tasti" },
+ { 181, "Rimuove il gioco dalla lista. I file del gioco rimarranno intatti" },
+ { 182, "Resa grafica:" },
+ { 183, "Destra" },
+ { 184, "Clic destro" },
+ { 185, "Clic destro" },
+ { 186, "Rotazione" },
+ { 187, "Volume effetti:" },
+ { 188, "SMB" },
+ { 189, "Salva" },
+ { 190, "Salvataggi:" },
+ { 191, "Salvataggi:" },
+ { 192, "Salva gioco:" },
+ { 193, "Scansione completa!" },
+ { 194, "%d cartelle analizzate..." },
+ { 195, "Menu principale di ScummVM" },
+ { 196, "ScummVM non ha potuto trovare un motore in grado di eseguire il gioco selezionato!" },
+ { 197, "ScummVM non ha potuto trovare nessun gioco nella cartella specificata!" },
+ { 198, "ScummVM non ha potuto aprire la cartella specificata!" },
+ { 199, "Cerca nella lista dei giochi" },
+ { 200, "Cerca:" },
+ { 201, "Seleziona SoundFont" },
+ { 202, "Seleziona un tema" },
+ { 203, "Seleziona la cartella di gioco aggiuntiva" },
+ { 204, "Seleziona un'azione e clicca 'Mappa'" },
+ { 205, "Seleziona la cartella dei temi dell'interfaccia" },
+ { 206, "Seleziona la cartella dei file aggiuntivi" },
+ { 207, "Seleziona la cartella dei plugin" },
+ { 208, "Seleziona la cartella dei salvataggi" },
+ { 209, "Seleziona la cartella per i salvataggi" },
+ { 210, "Seleziona la cartella contenente i file di gioco" },
+ { 211, "Sensibilit\340" },
+ { 212, "Server:" },
+ { 213, "Condivisione:" },
+ { 214, "Breve identificatore di gioco utilizzato per il riferimento a salvataggi e per l'esecuzione del gioco dalla riga di comando" },
+ { 215, "Mostra tastiera" },
+ { 216, "Mostra cursore del mouse" },
+ { 217, "Mostra i sottotitoli e attiva le voci" },
+ { 218, "Mostra/nascondi cursore" },
+ { 219, "Salta" },
+ { 220, "Salta battuta" },
+ { 221, "Salta testo" },
+ { 222, "Aggancia ai bordi" },
+ { 223, "Ridimensionamento software (di buona qualit\340, ma pi\371 lento)" },
+ { 224, "Suono on/off" },
+ { 225, "SoundFont \350 supportato da alcune schede audio, Fluidsynth e Timidity" },
+ { 226, "SoundFont:" },
+ { 227, "Voci" },
+ { 228, "Modalit\340 di resa grafica speciali supportate da alcuni giochi" },
+ { 229, "Volume degli effetti sonori" },
+ { 230, "Specifica il dispositivo audio predefinito per l'output General MIDI" },
+ { 231, "Specifica il dispositivo audio predefinito per l'output Roland MT-32/LAPC1/CM32l/CM64" },
+ { 232, "Specifica il dispositivo di output audio o l'emulatore della scheda audio" },
+ { 233, "Specifica il percorso di ulteriori dati usati dai giochi o da ScummVM" },
+ { 234, "Specifica il percorso di ulteriori dati usati dal gioco" },
+ { 235, "Specifica il dispositivo audio o l'emulatore della scheda audio preferiti" },
+ { 236, "Specifica dove archiviare i salvataggi" },
+ { 237, "Voci" },
+ { 238, "Volume voci:" },
+ { 239, "Renderer standard (16bpp)" },
+ { 240, "Esegue il gioco selezionato" },
+ { 241, "Stato:" },
+ { 242, "Sub" },
+ { 243, "Velocit\340 testo:" },
+ { 244, "Sottotitoli" },
+ { 245, "Cambia personaggio" },
+ { 246, "Un tocco per il clic sinistro, doppio tocco per il clic destro" },
+ { 247, "Testo e voci:" },
+ { 248, "La cartella scelta \350 in sola lettura. Si prega di sceglierne un'altra." },
+ { 249, "Percorso tema:" },
+ { 250, "Tema:" },
+ { 251, "Questo ID di gioco \350 gi\340 in uso. Si prega di sceglierne un'altro." },
+ { 252, "Questo gioco non supporta il caricamento di salvataggi dalla schermata di avvio." },
+ { 253, "Ora: " },
+ { 254, "Attesa per l'avvio della rete" },
+ { 255, "Compensa X del tocco" },
+ { 256, "Compensa Y del tocco" },
+ { 257, "Modalit\340 touchpad disattivata." },
+ { 258, "Modalit\340 touchpad attivata." },
+ { 259, "Roland MT-32 effettivo (disattiva emulazione GM)" },
+ { 260, "Disattiva la mappatura General MIDI per i giochi con colonna sonora Roland MT-32" },
+ { 261, "Sconosciuto" },
+ { 262, "Errore sconosciuto" },
+ { 263, "Smonta DVD" },
+ { 264, "Smonta SMB" },
+ { 265, "Non ridimensionato (devi scorrere a sinistra e a destra)" },
+ { 266, "Modalit\340 colore non supportata" },
+ { 267, "Salvataggio senza titolo" },
+ { 268, "Su" },
+ { 269, "Utilizza generazione di suono sia MIDI che AdLib" },
+ { 270, "Utilizza il controllo del cursore stile trackpad del portatile" },
+ { 271, "Nome utente:" },
+ { 272, "Utilizzo del driver SDL " },
+ { 273, "Underscan verticale:" },
+ { 274, "Video" },
+ { 275, "Tastiera virtuale" },
+ { 276, "Volume" },
+ { 277, "MIDI Windows" },
+ { 278, "Autorizzazione di scrittura negata" },
+ { 279, "Scrittura dati fallita" },
+ { 280, "S\354" },
+ { 281, "Devi riavviare ScummVM affinch\351 le modifiche abbiano effetto." },
+ { 282, "Zona" },
+ { 283, "Zoom indietro" },
+ { 284, "Zoom avanti" },
+ { 285, "ogni 10 minuti" },
+ { 286, "ogni 15 minuti" },
+ { 287, "ogni 30 minuti" },
+ { 288, "ogni 5 minuti" },
+ { 289, "~I~nfo" },
+ { 290, "~A~ggiungi gioco..." },
+ { 291, "~A~nnulla" },
+ { 292, "~C~hiudi" },
+ { 293, "~M~odifica gioco..." },
+ { 294, "~A~iuto" },
+ { 295, "Controlli combattimento di ~I~ndy" },
+ { 296, "~T~asti" },
+ { 297, "~M~odalit\340 mancini" },
+ { 298, "~C~arica" },
+ { 299, "~C~arica..." },
+ { 300, "~S~uccessivi" },
+ { 301, "~O~K" },
+ { 302, "~O~pzioni" },
+ { 303, "~O~pzioni..." },
+ { 304, "~P~recedenti" },
+ { 305, "C~h~iudi" },
+ { 306, "~R~imuovi gioco" },
+ { 307, "~R~ipristina" },
+ { 308, "~V~ai a schermata di avvio" },
+ { 309, "~S~alva" },
+ { 310, "~G~ioca" },
+ { 311, "~T~ransizioni attive" },
+ { 312, "~E~ffetto acqua attivo" },
+ { 313, "Modalit\340 ~Z~ip attivata" },
+ { -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-12 17:44+0200\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>\nLanguage: Catalan\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\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:" },
+ { 127, "Dispositiu MT32:" },
+ { 128, "Emulador de MT-32" },
+ { 129, "Escalat de la pantalla principal:" },
+ { 130, "Mapeja" },
+ { 131, "Addici\363 Massiva..." },
+ { 132, "Men\372" },
+ { 133, "Misc" },
+ { 134, "Mode combinat AdLib/MIDI" },
+ { 135, "Munta el DVD" },
+ { 136, "Munta SMB" },
+ { 137, "Clic del ratol\355" },
+ { 138, "Funci\363 M\372ltiple" },
+ { 139, "Dispositiu GM:" },
+ { 140, "Volum de la m\372sica:" },
+ { 141, "Silenciar tot" },
+ { 142, "Nom:" },
+ { 143, "Xarxa inactiva" },
+ { 144, "Xarxa no iniciada (%d)" },
+ { 145, "Xarxa activa" },
+ { 146, "Xarxa activa, compartici\363 muntada" },
+ { 147, "Mai" },
+ { 148, "No" },
+ { 149, "No hi ha data desada" },
+ { 150, "Sense m\372sica" },
+ { 151, "No hi ha temps de joc desat" },
+ { 152, "No hi ha hora desada" },
+ { 153, "Cap" },
+ { 154, "Normal (sense escalar)" },
+ { 155, "D'acord" },
+ { 156, "Freq\374\350ncia de sortida:" },
+ { 157, "Fer canvis sobre les opcions globals de MIDI" },
+ { 158, "Fer canvis sobre les opcions globals d'\340udio" },
+ { 159, "Fer canvis sobre les opcions globals de gr\340fics" },
+ { 160, "Fer canvis sobre les opcions globals de volum" },
+ { 161, "Emulador d'Altaveu de PC" },
+ { 162, "Contrasenya:" },
+ { 163, "El cam\355 no \351s un directori" },
+ { 164, "El cam\355 no \351s un fitxer" },
+ { 165, "El cam\355 no existeix" },
+ { 166, "Camins" },
+ { 167, "Pausa" },
+ { 168, "Seleccioneu el joc:" },
+ { 169, "Plataforma per la que el joc es va dissenyar originalment" },
+ { 170, "Plataforma:" },
+ { 171, "Temps de joc: " },
+ { 172, "Seleccioneu una acci\363" },
+ { 173, "Cam\355 dels connectors:" },
+ { 174, "Dispositiu Preferit:" },
+ { 175, "Premeu la tecla a associar" },
+ { 176, "Surt" },
+ { 177, "Surt de ScummVM" },
+ { 178, "S'ha denegat el perm\355s de lectura" },
+ { 179, "Ha fallat la lectura" },
+ { 180, "Remapeja les tecles" },
+ { 181, "Elimina un joc de la llista. Els fitxers de dades del joc es mantenen intactes" },
+ { 182, "Mode de pintat:" },
+ { 183, "Dreta" },
+ { 184, "Clic dret" },
+ { 185, "Clic dret" },
+ { 186, "Rotar" },
+ { 187, "Volum dels efectes:" },
+ { 188, "SMB" },
+ { 189, "Desa" },
+ { 190, "Cam\355 de les Partides:" },
+ { 191, "Cam\355 de les Partides: " },
+ { 192, "Desa la partida:" },
+ { 193, "S'ha acabat la cerca!" },
+ { 194, "S'han cercat %d directoris ..." },
+ { 195, "Men\372 Principal de ScummVM" },
+ { 196, "ScummVM no ha pogut trobar cap motor capa\347 d'executar el joc seleccionat!" },
+ { 197, "ScummVM no ha pogut trobar cap joc al directori especificat!" },
+ { 198, "ScummVM no ha pogut obrir el directori especificat!" },
+ { 199, "Cerca a la llista de jocs" },
+ { 200, "Cerca:" },
+ { 201, "Seleccioneu el fitxer SoundFont" },
+ { 202, "Seleccioneu un Tema" },
+ { 203, "Seleccioneu el directori addicional del joc" },
+ { 204, "Seleccioneu una acci\363 i cliqueu 'Mapeja'" },
+ { 205, "Seleccioneu el directori dels temes de la Interf\355cie d'Usuari" },
+ { 206, "Seleccioneu el directori dels fitxers extra" },
+ { 207, "Seleccioneu el directori dels connectors" },
+ { 208, "Seleccioneu el directori de les partides desades" },
+ { 209, "Seleccioneu el directori de les partides desades" },
+ { 210, "Seleccioneu el directori amb les dades del joc" },
+ { 211, "Sensibilitat" },
+ { 212, "Servidor:" },
+ { 213, "Compartici\363:" },
+ { 214, "Identificador de joc curt utilitzat per referir-se a les partides i per executar el joc des de la l\355nia de comandes" },
+ { 215, "Mostra el teclat" },
+ { 216, "Mostra el cursor del ratol\355" },
+ { 217, "Mostra els subt\355tols i reprodueix la veu" },
+ { 218, "Mostra/Oculta el cursor" },
+ { 219, "Salta" },
+ { 220, "Salta la l\355nia" },
+ { 221, "Salta el text" },
+ { 223, "Escalat per software (bona qualitat, per\362 m\351s lent)" },
+ { 224, "So engegat/parat" },
+ { 225, "Algunes targes de so, Fluidsynth i Timidity suporten SoundFont" },
+ { 226, "Fitxer SoundFont:" },
+ { 227, "Veus" },
+ { 228, "Modes de dispersi\363 especials suportats per alguns jocs" },
+ { 229, "Volum dels sons d'efectes especials" },
+ { 230, "Especifica el dispositiu de so per defecte per a la sortida General MIDI" },
+ { 231, "Especifica el dispositiu de so per defecte per a la sortida de Roland MT-32/LAPC1/CM32l/CM64" },
+ { 232, "Especifica el dispositiu de so o l'emulador de tarja de so de sortida" },
+ { 233, "Especifica el cam\355 de les dades addicionals utilitzades per tots els jocs o pel ScummVM" },
+ { 234, "Especifica el cam\355 de dades addicionals utilitzades pel joc" },
+ { 235, "Especifica el dispositiu de so o l'emulador de tarja de so preferit" },
+ { 236, "Especifica on es desaran les partides" },
+ { 237, "Veus" },
+ { 238, "Volum de la veu:" },
+ { 239, "Pintat est\340ndard (16bpp)" },
+ { 240, "Iniciant el joc seleccionat" },
+ { 241, "Estat:" },
+ { 242, "Subt" },
+ { 243, "Velocitat dels subt\355tols:" },
+ { 244, "Subt\355tols" },
+ { 245, "Commuta el personatge" },
+ { 246, "Toc per a clic esquerre, doble toc per a clic dret" },
+ { 247, "Text i Veus:" },
+ { 248, "No es pot escriure al directori seleccionat. Si us plau, escolliu-ne un altre." },
+ { 249, "Cam\355 dels Temes:" },
+ { 250, "Tema:" },
+ { 251, "Aquest identificador de joc ja est\340 usat. Si us plau, trieu-ne un altre." },
+ { 252, "Aquest joc no suporta la c\340rrega de partides des del llan\347ador." },
+ { 253, "Hora: " },
+ { 255, "Despla\347ament X del toc" },
+ { 256, "Despla\347ament Y del toc" },
+ { 257, "Mode Touchpad desactivat." },
+ { 258, "Mode Touchpad activat." },
+ { 259, "Roland MT-32 real (desactiva l'emulaci\363 GM)" },
+ { 260, "Desactiva la conversi\363 General MIDI pels jocs que tenen banda sonora per a Roland MT-32" },
+ { 261, "Desconegut" },
+ { 262, "Error desconegut" },
+ { 263, "Desmunta el DVD" },
+ { 264, "Desmunta SMB" },
+ { 265, "Sense escalar (haureu de despla\347ar-vos a esquerra i dreta)" },
+ { 266, "Mode de color no suportat" },
+ { 267, "Partida sense t\355tol" },
+ { 268, "Amunt" },
+ { 269, "Utilitza MIDI i la generaci\363 de so AdLib alhora" },
+ { 270, "Utilitza el control del cursor a l'estil del trackpad dels port\340tils" },
+ { 271, "Nom d'usuari:" },
+ { 272, "Utilitzant el controlador SDL " },
+ { 274, "V\355deo" },
+ { 275, "Teclat virtual" },
+ { 276, "Volum" },
+ { 277, "MIDI de Windows" },
+ { 278, "S'ha denegat el perm\355s d'escriptura" },
+ { 279, "Ha fallat l'escriptura de dades" },
+ { 280, "S\355" },
+ { 281, "Heu de reiniciar ScummVM perqu\350 tots els canvis tingui efecte." },
+ { 282, "Zona" },
+ { 283, "Redueix" },
+ { 284, "Amplia" },
+ { 285, "cada 10 minuts" },
+ { 286, "cada 15 minuts" },
+ { 287, "cada 30 minuts" },
+ { 288, "cada 5 minuts" },
+ { 289, "~Q~uant a" },
+ { 290, "~A~fegeix Joc..." },
+ { 291, "~C~ancel\267la" },
+ { 292, "~T~anca" },
+ { 293, "~E~dita Joc..." },
+ { 294, "~A~juda" },
+ { 295, "Controls de lluita de l'~I~ndy" },
+ { 296, "~T~ecles" },
+ { 297, "Mode ~e~squerr\340" },
+ { 298, "C~a~rrega" },
+ { 299, "~C~arrega..." },
+ { 300, "~S~eg\374ent" },
+ { 301, "~D~'acord" },
+ { 302, "~O~pcions" },
+ { 303, "~O~pcions..." },
+ { 304, "~A~nterior" },
+ { 305, "~T~anca" },
+ { 306, "~S~uprimeix Joc" },
+ { 307, "~C~ontinua" },
+ { 308, "~R~etorna al Llan\347ador" },
+ { 309, "~D~esa" },
+ { 310, "~I~nicia" },
+ { 311, "~T~ransicions activades" },
+ { 312, "~E~fecte de l'aigua activat" },
+ { 313, "Mode ~Z~ip activat" },
+ { -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-12 17:44+0200\nPO-Revision-Date: 2009-11-25 07:42-0500\nLast-Translator: Alex Bevilacqua <alexbevi@gmail.com>\nLanguage-Team: Hungarian\nLanguage: \nMIME-Version: 1.0\nContent-Type: text/plain; charset=cp1250\nContent-Transfer-Encoding: 8bit\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:" },
+ { 127, "Zene mennyis\351g:" },
+ { 134, "Vegyes AdLib/MIDI m\363d" },
+ { 139, "Zene mennyis\351g:" },
+ { 140, "Zene mennyis\351g:" },
+ { 141, "Muta \326sszes" },
+ { 147, "Soha" },
+ { 148, "Semmi" },
+ { 153, "Semmi" },
+ { 155, "Igen" },
+ { 156, "Kimeneti teljes\355tm\351ny:" },
+ { 166, "\326sv\351nyek" },
+ { 167, "\326sv\351nyek" },
+ { 182, "Renderel\351si m\363d:" },
+ { 187, "SFX mennyis\351ge" },
+ { 190, "Extra \332tvonal:" },
+ { 212, "Soha" },
+ { 237, "Csak a besz\351d" },
+ { 238, "Besz\351d mennyis\351g:" },
+ { 243, "Felirat sebess\351g:" },
+ { 244, "Csak feliratok" },
+ { 247, "Sz\366veg \351s besz\351d:" },
+ { 250, "T\351ma:" },
+ { 253, "T\351ma:" },
+ { 259, "Igaz Roland MT-32 (megb\351n\355t GM emul\341ci\363)" },
+ { 272, "Zenei vezet :" },
+ { 276, "Volumene" },
+ { 282, "Semmi" },
+ { 285, "10 percenk\351nt" },
+ { 286, "15 percenk\351nt" },
+ { 287, "30 percenk\351nt" },
+ { 288, "5 percenk\351nt" },
+ { 296, "Kulcsok" },
+ { 297, "Renderel\351si m\363d:" },
+ { 301, "Igen" },
+ { -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-12 17:44+0200\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>\nLanguage: Deutsch\nMIME-Version: 1.0\nContent-Type: text/plain; charset=iso-8859-1\nContent-Transfer-Encoding: 8bit\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:" },
+ { 127, "MT32-Ger\344t:" },
+ { 128, "MT-32-Emulation" },
+ { 129, "Hauptbildschirm-Skalierung:" },
+ { 130, "Zuweisen" },
+ { 131, "Durchsuchen" },
+ { 132, "Men\374" },
+ { 133, "Sonstiges" },
+ { 134, "AdLib-/MIDI-Modus" },
+ { 135, "DVD einbinden" },
+ { 136, "SMB einbinden" },
+ { 137, "Mausklick" },
+ { 138, "Multifunktion" },
+ { 139, "Musikger\344t:" },
+ { 140, "Musiklautst\344rke:" },
+ { 141, "Alles aus" },
+ { 142, "Name:" },
+ { 143, "Netzwerk ist aus." },
+ { 144, "Netzwerk nicht gestartet (%d)" },
+ { 145, "Netzwerk gestartet" },
+ { 146, "Netzwerk gestartet, \366ffentliches Verzeichnis eingebunden" },
+ { 147, "Niemals" },
+ { 148, "Nein" },
+ { 149, "Kein Datum gespeichert" },
+ { 150, "Keine Musik" },
+ { 151, "Keine Spielzeit gespeichert" },
+ { 152, "Keine Zeit gespeichert" },
+ { 153, "-" },
+ { 154, "Normal (keine Skalierung)" },
+ { 155, "OK" },
+ { 156, "Ausgabefrequenz:" },
+ { 157, "Globale MIDI-Einstellungen \374bergehen" },
+ { 158, "Globale Audioeinstellungen \374bergehen" },
+ { 159, "Globale Grafikeinstellungen \374bergehen" },
+ { 160, "Globale Lautst\344rke-Einstellungen \374bergehen" },
+ { 161, "PC-Lautsprecher-Emulator" },
+ { 162, "Passwort:" },
+ { 163, "Ung\374ltiges Verzeichnis" },
+ { 164, "Pfad ist keine Datei." },
+ { 165, "Verzeichnis existiert nicht." },
+ { 166, "Pfade" },
+ { 167, "Pause" },
+ { 168, "Spiel ausw\344hlen:" },
+ { 169, "Plattform, f\374r die das Spiel urspr\374nglich erstellt wurde" },
+ { 170, "Plattform:" },
+ { 171, "Spieldauer: " },
+ { 172, "Bitte eine Aktion ausw\344hlen" },
+ { 173, "Plugin-Pfad:" },
+ { 174, "Standard-Ger\344t:" },
+ { 175, "Taste dr\374cken, um sie zuzuweisen" },
+ { 176, "Beenden" },
+ { 177, "ScummVM beenden" },
+ { 178, "Lese-Berechtigung nicht vorhanden" },
+ { 179, "Lesefehler aufgetreten" },
+ { 180, "Tasten neu zuweisen" },
+ { 181, "Spiel aus der Liste entfernen. Die Spieldateien bleiben erhalten." },
+ { 182, "Render-Modus:" },
+ { 183, "Rechts" },
+ { 184, "Rechtsklick" },
+ { 185, "Rechtsklick" },
+ { 186, "Drehen" },
+ { 187, "Effektlautst\344rke:" },
+ { 188, "SMB" },
+ { 189, "Speichern" },
+ { 190, "Spielst\344nde:" },
+ { 191, "Spielst\344nde: " },
+ { 192, "Speichern:" },
+ { 193, "Suchlauf abgeschlossen!" },
+ { 194, "%d Ordner durchsucht..." },
+ { 195, "ScummVM-Hauptmen\374" },
+ { 196, "ScummVM konnte keine Engine finden, um das Spiel zu starten!" },
+ { 197, "ScummVM kann in dem gew\344hlten Verzeichnis kein Spiel finden!" },
+ { 198, "ScummVM kann das gew\344hlte Verzeichnis nicht \366ffnen!" },
+ { 199, "In Spieleliste suchen" },
+ { 200, "Suchen:" },
+ { 201, "SoundFont ausw\344hlen" },
+ { 202, "Thema ausw\344hlen" },
+ { 203, "Verzeichnis mit zus\344tzlichen Dateien ausw\344hlen" },
+ { 204, "Aktion ausw\344hlen und \"Zuweisen\" klicken" },
+ { 205, "Verzeichnis f\374r Oberfl\344chen-Themen" },
+ { 206, "Verzeichnis f\374r zus\344tzliche Dateien ausw\344hlen" },
+ { 207, "Verzeichnis f\374r Erweiterungen ausw\344hlen" },
+ { 208, "Verzeichnis f\374r Spielst\344nde ausw\344hlen" },
+ { 209, "Verzeichnis f\374r Spielst\344nde ausw\344hlen" },
+ { 210, "Verzeichnis mit Spieldateien ausw\344hlen" },
+ { 211, "Empfindlichkeit" },
+ { 212, "Server:" },
+ { 213, "\326ffentliches Verzeichnis:" },
+ { 214, "Kurzer Spielname, um die Spielst\344nde zuzuordnen und das Spiel von der Kommandozeile aus starten zu k\366nnen" },
+ { 215, "Tastatur zeigen" },
+ { 216, "Mauszeiger anzeigen" },
+ { 217, "Untertitel anzeigen und Sprachausgabe aktivieren" },
+ { 218, "Cursor zeigen/verbergen" },
+ { 219, "\334berspringen" },
+ { 220, "Zeile \374berspringen" },
+ { 221, "Text \374berspringen" },
+ { 222, "An Ecken anheften" },
+ { 223, "Software-Skalierung (gute Qualit\344t, aber langsamer)" },
+ { 224, "Ton ein/aus" },
+ { 225, "SoundFont wird von einigen Soundkarten, Fluidsynth und Timidity unterst\374tzt." },
+ { 226, "SoundFont:" },
+ { 227, "Spr." },
+ { 228, "Spezielle Farbmischungsmethoden werden von manchen Spielen unterst\374tzt." },
+ { 229, "Lautst\344rke spezieller Soundeffekte" },
+ { 230, "Legt das standardm\344\337ige Musikwiedergabe-Ger\344t f\374r General-MIDI-Ausgabe fest." },
+ { 231, "Legt das standardm\344\337ige Tonwiedergabe-Ger\344t f\374r die Ausgabe von Roland MT-32/LAPC1/CM32l/CM64 fest." },
+ { 232, "Legt das Musikwiedergabe-Ger\344t oder den Soundkarten-Emulator fest." },
+ { 233, "Legt das Verzeichnis f\374r zus\344tzliche Spieldateien f\374r alle Spiele in ScummVM fest." },
+ { 234, "Legt das Verzeichnis f\374r zus\344tzliche Spieldateien fest." },
+ { 235, "Legt das bevorzugte Tonwiedergabe-Ger\344t oder den Soundkarten-Emulator fest." },
+ { 236, "Legt fest, wo die Spielst\344nde abgelegt werden." },
+ { 237, "Sprache" },
+ { 238, "Sprachlautst\344rke:" },
+ { 239, "Standard-Renderer (16bpp)" },
+ { 240, "Ausgew\344hltes Spiel starten" },
+ { 241, "Status:" },
+ { 242, "Untert." },
+ { 243, "Untertitel-Tempo:" },
+ { 244, "Untertitel" },
+ { 245, "Figur wechseln" },
+ { 246, "Tippen f\374r Linksklick, Doppeltippen f\374r Rechtsklick" },
+ { 247, "Text und Sprache:" },
+ { 248, "In das gew\344hlte Verzeichnis kann nicht geschrieben werden. Bitte ein anderes ausw\344hlen." },
+ { 249, "Themenpfad:" },
+ { 250, "Thema:" },
+ { 251, "Diese Spielkennung ist schon vergeben. Bitte eine andere w\344hlen." },
+ { 252, "F\374r dieses Spiel wird das Laden aus der Spieleliste heraus nicht unterst\374tzt." },
+ { 253, "Zeit: " },
+ { 254, "Zeit\374berschreitung beim Starten des Netzwerks" },
+ { 255, "Zu X-Position gehen" },
+ { 256, "Zu Y-Position gehen" },
+ { 257, "Touchpad-Modus ausgeschaltet." },
+ { 258, "Touchpad-Modus aktiviert." },
+ { 259, "Echte Roland-MT-32-Emulation (GM-Emulation deaktiviert)" },
+ { 260, "Schaltet die General-MIDI-Zuweisung f\374r Spiele mit Roland-MT-32-Audiospur aus." },
+ { 261, "Unbekannt" },
+ { 262, "Unbekannter Fehler" },
+ { 263, "DVD aush\344ngen" },
+ { 264, "SMB aush\344ngen" },
+ { 265, "Nicht skalieren (Sie m\374ssen nach links und nach rechts scrollen)" },
+ { 266, "Farbmodus nicht unterst\374tzt" },
+ { 267, "Unbenannt" },
+ { 268, "Hoch" },
+ { 269, "Benutzt MIDI und AdLib zur Sounderzeugung." },
+ { 270, "Den Trackpad-Style f\374r Maussteuerung benutzen" },
+ { 271, "Benutzername:" },
+ { 272, "SDL-Treiber verwenden" },
+ { 273, "Vertikale Bildverkleinerung:" },
+ { 274, "Video" },
+ { 275, "Virtuelle Tastatur" },
+ { 276, "Lautst\344rke" },
+ { 277, "Windows MIDI" },
+ { 278, "Schreib-Berechtigung nicht vorhanden" },
+ { 279, "Daten konnten nicht geschrieben werden." },
+ { 280, "Ja" },
+ { 281, "Sie m\374ssen ScummVM neustarten, um die Einstellungen zu \374bernehmen." },
+ { 282, "Zone" },
+ { 283, "Hineinzoomen" },
+ { 284, "Herauszoomen" },
+ { 285, "alle 10 Minuten" },
+ { 286, "alle 15 Minuten" },
+ { 287, "alle 30 Minuten" },
+ { 288, "alle 5 Minuten" },
+ { 289, "\334be~r~" },
+ { 290, "Spiel ~h~inzuf\374gen" },
+ { 291, "~A~bbrechen" },
+ { 292, "~S~chlie\337en" },
+ { 293, "Spielo~p~tionen" },
+ { 294, "~H~ilfe" },
+ { 295, "~K~ampfsteuerung f\374r Indiana Jones" },
+ { 296, "~T~asten" },
+ { 297, "~L~inke-Hand-Modus" },
+ { 298, "~L~aden" },
+ { 299, "~L~aden..." },
+ { 300, "~W~eiter" },
+ { 301, "~O~K" },
+ { 302, "~O~ptionen" },
+ { 303, "~O~ptionen" },
+ { 304, "~Z~ur\374ck" },
+ { 305, "~B~eenden" },
+ { 306, "Spiel ~e~ntfernen" },
+ { 307, "~F~ortsetzen" },
+ { 308, "Zur Spiele~l~iste zur\374ck" },
+ { 309, "~S~peichern" },
+ { 310, "~S~tarten" },
+ { 311, "\334ber~g~\344nge aktiviert" },
+ { 312, "~W~assereffekt aktiviert" },
+ { 313, "~Z~ip-Modus aktiviert" },
+ { -1, NULL }
+};
+
+struct PoLangEntry {
+ const char *lang;
+ const char *charset;
+ const PoMessageEntry *msgs;
+};
+
+const PoLangEntry _translations[] = {
+ { "ru_RU", "iso-8859-5", _translation_ru_RU },
+ { "fr_FR", "iso-8859-1", _translation_fr_FR },
+ { "it_IT", "iso-8859-1", _translation_it_IT },
+ { "ca_ES", "iso-8859-1", _translation_ca_ES },
+ { "hu_HU", "cp1250", _translation_hu_HU },
+ { "de_DE", "iso-8859-1", _translation_de_DE },
+ { 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;
+}
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/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/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 b4b39889cd..6c8d6108a4 100644
--- a/common/system.h
+++ b/common/system.h
@@ -385,7 +385,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();
@@ -881,7 +881,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..2e5a347489 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;
@@ -159,6 +163,11 @@ void NORETURN_PRE error(const char *s, ...) {
#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..093f26510f
--- /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::getSupportedLanguages() const {
+ TLangArray languages;
+
+ int total = po2c_getnumlangs();
+ for (int i = 0; i < total; i++) {
+ TLanguage lng(po2c_getlang(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::getSupportedLanguages() 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..277ac6f5c4
--- /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.
+ */
+ const TLangArray getSupportedLanguages() 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/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..521a12e4c7 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,9 +326,26 @@ 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;
-
+
for (int i = 0; g_gameOptions[i].desc; i++)
if (str.contains(g_gameOptions[i].desc))
res |= g_gameOptions[i].option;
@@ -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 d19e6cbac8..1f9806fe57 100755
--- a/configure
+++ b/configure
@@ -136,6 +136,8 @@ _enable_prof=no
# Default vkeybd/keymapper options
_vkeybd=no
_keymapper=no
+# GUI translation options
+_translation=yes
# Default platform settings
_backend=sdl
_endian=unknown
@@ -341,7 +343,7 @@ get_system_exe_extension() {
arm-riscos)
_exeext=",ff8"
;;
- dreamcast | gamecube | nds | ps2 | psp | wii)
+ dreamcast | gamecube | ds | ps2 | psp | wii)
_exeext=".elf"
;;
gp2x-linux)
@@ -625,7 +627,7 @@ Usage: $0 [OPTIONS]...
Configuration:
-h, --help display this help and exit
--backend=BACKEND backend to build (dc, gp2x, gp2xwiz, iphone,
- linuxmoto, nds, null, ps2, psp, sdl, wii, wince)
+ linuxmoto, ds, null, ps2, psp, sdl, wii, wince)
[sdl]
Installation directories:
@@ -655,7 +657,7 @@ Special configuration feature:
gamecube for Nintendo GameCube
iphone for Apple iPhone
linupy for Yopy PDA
- nds for Nintendo DS
+ ds for Nintendo DS
ps2 for PlayStation 2
psp for PlayStation Portable
wii for Nintendo Wii
@@ -676,6 +678,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
@@ -760,6 +763,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 ;;
@@ -944,8 +949,8 @@ motomagx)
_host_cpu=arm
_host_alias=arm-linux-gnueabi
;;
-nds)
- _host_os=nds
+ds)
+ _host_os=ds
_host_cpu=arm
_host_alias=arm-eabi
;;
@@ -1002,7 +1007,7 @@ wince)
android)
_host_os=android
_host_cpu=arm
- _host_alias=arm-android-eabi
+ _host_alias=arm-oe-linux-androideabi
;;
*)
if test -n "$_host"; then
@@ -1037,7 +1042,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
@@ -1063,7 +1070,7 @@ esac
# Platform specific sanity checks
#
case $_host_os in
-gamecube | nds | wii)
+gamecube | ds | wii)
if test -z "$DEVKITPRO"; then
echo "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to devkitPRO>"
exit 1
@@ -1131,9 +1138,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
@@ -1351,7 +1361,8 @@ case $_host_os in
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"
@@ -1380,9 +1391,14 @@ case $_host_os in
mint*)
DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE"
;;
- nds)
- # TODO nds
+ 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 -mthumb-interwork -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"
;;
os2-emx*)
DEFINES="$DEFINES -DUNIX"
@@ -1404,7 +1420,8 @@ case $_host_os in
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"
@@ -1486,6 +1503,7 @@ if test -n "$_host"; then
_build_hq_scalers="no"
_mt32emu="no"
_vkeybd="yes"
+ _port_mk="backends/platform/gp2x/gp2x-bundle.mk"
;;
gp2xwiz)
DEFINES="$DEFINES -DUNIX -DGP2XWIZ -DNDEBUG"
@@ -1501,6 +1519,7 @@ if test -n "$_host"; then
_build_hq_scalers="no"
_mt32emu="no"
_vkeybd="yes"
+ _port_mk="backends/platform/gp2xwiz/gp2xwiz-bundle.mk"
;;
iphone)
DEFINES="$DEFINES -DIPHONE -DUNIX"
@@ -1557,24 +1576,23 @@ if test -n "$_host"; then
_vkeybd="yes"
_port_mk="backends/platform/linuxmoto/linuxmoto.mk"
;;
- nds)
+ ds)
# 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 -DREDUCE_MEMORY_USAGE -DSTREAM_AUDIO_FROM_DISK"
+ DEFINES="$DEFINES -DDISABLE_DOSBOX_OPL"
DEFINES="$DEFINES -DDISABLE_TEXT_CONSOLE -DDISABLE_COMMAND_LINE"
_need_memalign=yes
- _backend="nds"
+ 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_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'
;;
neuros)
DEFINES="$DEFINES -DUNIX -DNEUROS"
@@ -1666,7 +1684,6 @@ if test -n "$_host"; then
;;
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'
@@ -1675,7 +1692,6 @@ if test -n "$_host"; then
add_line_to_config_mk 'USE_ARM_COSTUME_ASM = 1'
_backend="android"
_port_mk="backends/platform/android/android.mk"
- _build_hq_scalers="no"
;;
*)
echo "WARNING: Unknown target, continuing with auto-detected values"
@@ -1978,7 +1994,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
@@ -2314,6 +2330,31 @@ if test "$_keymapper" = yes ; then
DEFINES="$DEFINES -DENABLE_KEYMAPPER"
fi
+# Check whether to build translation support
+#
+echo_n "Building translation support... "
+add_to_config_mk_if_yes $_translation 'USE_TRANSLATION = 1'
+add_to_config_h_if_yes $_translation '#define 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
+
+ add_to_config_h_if_yes $_detectlang '#define USE_DETECTLANG'
+ if test "$_detectlang" = yes ; then
+ echo "with runtime language detection)"
+ else
+ echo "without runtime language detection)"
+ fi
+fi
+
#
# Figure out installation directories
#
@@ -2408,8 +2449,11 @@ case $_backend in
LIBS="$LIBS `$_sdlconfig --prefix="$_sdlpath" --libs`"
DEFINES="$DEFINES -DSDL_BACKEND -DLINUXMOTO"
;;
- nds)
- # TODO nds
+ 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'
;;
null)
DEFINES="$DEFINES -DUSE_NULL_DRIVER"
@@ -2424,14 +2468,7 @@ 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"
;;
samsungtv)
find_sdlconfig
@@ -2463,12 +2500,36 @@ case $_backend in
LIBS="$LIBS -static -lSDL"
;;
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="$LIBS -lgcc -lstdc++ -llog -lGLESv1_CM -lEGL"
+ 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'
;;
*)
echo "support for $_backend backend not implemented in configure script yet"
@@ -2485,7 +2546,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)
+ mingw* | dreamcast | wii | gamecube | ds | psp | wince | amigaos* | android)
CXXFLAGS="$CXXFLAGS -W -Wno-unused-parameter"
;;
*)
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/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..d8820f3397
--- /dev/null
+++ b/dists/iphone/icon-72.png
Binary files differ
diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp
index b149b43ad7..315763a6da 100644
--- a/engines/advancedDetector.cpp
+++ b/engines/advancedDetector.cpp
@@ -208,6 +208,7 @@ static void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription *
desc["extra"] = realDesc->extra;
desc.setGUIOptions(realDesc->guioptions | params.guioptions);
+ desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(realDesc->language));
}
GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const {
@@ -305,7 +306,7 @@ 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::updateGameGUIOptions(agdDesc->guioptions | params.guioptions, getGameGUIOptionsDescriptionLanguage(agdDesc->language));
debug(2, "Running %s", toGameDescriptor(*agdDesc, params.list).description().c_str());
if (!createInstance(syst, engine, agdDesc))
@@ -340,24 +341,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 +381,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.
diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h
index 370d958ce6..de4fc3bbf8 100644
--- a/engines/advancedDetector.h
+++ b/engines/advancedDetector.h
@@ -190,6 +190,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..4a994b731a 100644
--- a/engines/agi/agi.cpp
+++ b/engines/agi/agi.cpp
@@ -272,20 +272,19 @@ 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();
_system->delayMillis(10);
_system->updateScreen();
}
- m = _tickTimer;
+ _lastTickTimer = _tickTimer;
}
void AgiEngine::agiTimerFunctionLow(void *refCon) {
@@ -506,13 +505,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 +535,7 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
_allowSynthetic = false;
_tickTimer = 0;
+ _lastTickTimer = 0;
_intobj = NULL;
@@ -556,7 +549,7 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas
_restartGame = false;
- _oldMode = -1;
+ _oldMode = INPUT_NONE;
_predictiveDialogRunning = false;
_predictiveDictText = NULL;
@@ -569,6 +562,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 +580,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))) {
+ 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;
}
}
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..e881b092e3 100644
--- a/engines/agi/console.cpp
+++ b/engines/agi/console.cpp
@@ -64,7 +64,7 @@ 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 +76,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 +88,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 +99,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 +125,8 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) {
}
}
+ DebugPrintf("Unknown opcode\n");
+
return true;
}
@@ -243,6 +250,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/cycle.cpp b/engines/agi/cycle.cpp
index 10df40556f..c185c3efb3 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() {
@@ -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 || 1)
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..072ab0114f 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,88 @@ 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 +1276,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 +1301,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 +1334,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 +1399,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 +1448,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 +1472,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 || 1) {
+ _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 +1552,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 +1771,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 +1785,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 +1800,7 @@ int AgiEngine::runLogic(int n) {
}
} else {
_sprites->blitBoth();
+ _sprites->commitBoth();
do {
mainCycle();
} while (!_debug.steps && _debug.enabled);
@@ -1816,6 +1810,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 +1825,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 +1842,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 +1860,7 @@ int AgiEngine::runLogic(int n) {
void AgiEngine::executeAgiCommand(uint8 op, uint8 *p) {
debugC(2, kDebugLevelScripts, "%s(%d %d %d)", logicNamesCmd[op].name, p[0], p[1], p[2]);
- 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/agi/sound_coco3.h b/engines/agi/sound_coco3.h
new file mode 100644
index 0000000000..b60f1937cd
--- /dev/null
+++ b/engines/agi/sound_coco3.h
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef AGI_SOUND_COCO3_H
+#define AGI_SOUND_COCO3_H
+
+#include "sound/audiostream.h"
+
+namespace Agi {
+
+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);
+ }
+};
+
+class SoundGenCoCo3 : public SoundGen, public Audio::AudioStream {
+public:
+ SoundGenCoCo3(AgiEngine *vm, Audio::Mixer *pMixer);
+ ~SoundGenCoCo3();
+
+ 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;
+ }
+};
+
+} // End of namespace Agi
+
+#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..25118b69a6 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->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
@@ -466,11 +458,11 @@ void SpritesMgr::blitSprites(SpriteList& l) {
*/
void SpritesMgr::commitUpdSprites() {
- commitSprites(_sprUpd);
+ commitSprites(_sprUpd, true);
}
void SpritesMgr::commitNonupdSprites() {
- commitSprites(_sprNonupd);
+ commitSprites(_sprNonupd, true);
}
// check moves in both lists
@@ -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);
}
/**
@@ -691,15 +682,15 @@ void SpritesMgr::showObj(int n) {
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 +702,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 +714,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..45244bb292 100644
--- a/engines/agi/view.cpp
+++ b/engines/agi/view.cpp
@@ -294,37 +294,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 +311,7 @@ void AgiEngine::startUpdate(VtEntry *v) {
v->flags |= UPDATE;
_sprites->blitBoth();
+ _sprites->commitBoth();
}
}
@@ -351,6 +325,7 @@ void AgiEngine::stopUpdate(VtEntry *v) {
v->flags &= ~UPDATE;
_sprites->blitBoth();
+ _sprites->commitBoth();
}
}
@@ -393,7 +368,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/agos/agos.cpp b/engines/agos/agos.cpp
index 6502866e8d..1b7802acb6 100644
--- a/engines/agos/agos.cpp
+++ b/engines/agos/agos.cpp
@@ -201,19 +201,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;
@@ -556,10 +556,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);
@@ -630,9 +630,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");
@@ -647,7 +649,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
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 3bbc0624aa..f3ec948f0f 100644
--- a/engines/agos/event.cpp
+++ b/engines/agos/event.cpp
@@ -479,7 +479,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) {
@@ -566,7 +566,7 @@ void AGOSEngine_Feeble::timerProc() {
_videoLockOut |= 2;
if (!(_videoLockOut & 0x10)) {
- _syncFlag2 ^= 1;
+ _syncFlag2 = !_syncFlag2;
if (!_syncFlag2) {
processVgaEvents();
} else {
@@ -635,7 +635,7 @@ void AGOSEngine_PN::timerProc() {
processVgaEvents();
processVgaEvents();
- _cepeFlag ^= 1;
+ _cepeFlag = !_cepeFlag;
if (!_cepeFlag)
processVgaEvents();
}
@@ -661,7 +661,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..5fc2a64416 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,7 +598,7 @@ bool AGOSEngine::processSpecialKeys() {
syncSoundSettings();
break;
case 'm':
- _musicPaused ^= 1;
+ _musicPaused = !_musicPaused;
if (_midiEnabled) {
_midi.pause(_musicPaused);
}
@@ -606,14 +606,16 @@ bool AGOSEngine::processSpecialKeys() {
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/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/detection.cpp b/engines/cine/detection.cpp
index fcfa1f7f20..b92ad8a0a2 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 {
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..b5adebcd0b 100644
--- a/engines/cine/saveload.cpp
+++ b/engines/cine/saveload.cpp
@@ -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);
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/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/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..e1025e698a 100644
--- a/engines/draci/detection.cpp
+++ b/engines/draci/detection.cpp
@@ -94,7 +94,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/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/drascula/actors.cpp b/engines/drascula/actors.cpp
index ff46d8201a..33cb7fd478 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();
@@ -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/engines/sci/graphics/gui32.h b/engines/drascula/console.cpp
index 99eb03b321..d017468285 100644
--- a/engines/sci/graphics/gui32.h
+++ b/engines/drascula/console.cpp
@@ -23,46 +23,41 @@
*
*/
-#ifndef SCI_GRAPHICS_GUI32_H
-#define SCI_GRAPHICS_GUI32_H
+#include "drascula/console.h"
+#include "gui/debugger.h"
+#include "drascula/drascula.h"
-#include "sci/graphics/helpers.h"
+namespace Drascula {
-namespace Sci {
+Console::Console(DrasculaEngine *vm) : GUI::Debugger(), _vm(vm) {
+ DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room));
+}
-class GfxCursor;
-class GfxScreen;
-class GfxPalette;
-class GfxCache;
-class GfxCoordAdjuster32;
-class GfxCompare;
-class GfxFrameout;
-class GfxPaint32;
+Console::~Console() {
+}
-class SciGui32 {
-public:
- SciGui32(SegManager *segMan, SciEvent *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor);
- ~SciGui32();
+void Console::preEnter() {
+}
- void init();
+void Console::postEnter() {
+}
- void textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight);
+bool Console::Cmd_Room(int argc, const char **argv) {
+ if (argc < 2) {
+ DebugPrintf("Usage: changeCard <card>\n");
+ return true;
+ }
- void drawRobot(GuiResourceId robotId);
+ int roomNum = atoi(argv[1]);
-protected:
- GfxCursor *_cursor;
- GfxScreen *_screen;
- GfxPalette *_palette;
- GfxCache *_cache;
- GfxCoordAdjuster32 *_coordAdjuster;
- GfxCompare *_compare;
- GfxFrameout *_frameout;
- GfxPaint32 *_paint32;
+ _vm->loadedDifferentChapter = 0;
+ _vm->enterRoom(roomNum);
+ _vm->selectVerb(kVerbNone);
+ _vm->clearRoom();
+ _vm->loadPic(roomNum, _vm->bgSurface, HALF_PAL);
+ _vm->selectionMade = 0;
-private:
-};
+ return false;
+}
-} // End of namespace Sci
-
-#endif
+} // End of namespace Drascula
diff --git a/backends/platform/ds/arm9/source/portdefs.cpp b/engines/drascula/console.h
index 0dcdc1d5a3..33e2f626e4 100644
--- a/backends/platform/ds/arm9/source/portdefs.cpp
+++ b/engines/drascula/console.h
@@ -8,28 +8,44 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
- *
+
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+
* You 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 <string.h>
-#include "nds/dma.h"
-#include "osystem_ds.h"
+#ifndef DRASCULA_CONSOLE_H
+#define DRASCULA_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace Drascula {
+
+class DrasculaEngine;
+
+class Console : public GUI::Debugger {
+public:
+ Console(DrasculaEngine *vm);
+ virtual ~Console(void);
+
+protected:
+ virtual void preEnter();
+ virtual void postEnter();
+
+private:
+ DrasculaEngine *_vm;
-/*
-extern "C" time_t __wrap_time(time_t* t) {
- if (t) {
- *t = OSystem_DS::instance()->getMillis() / 1000;
- }
+ bool Cmd_Room(int argc, const char **argv);
+};
- return OSystem_DS::instance()->getMillis() / 1000;
-}
-*/
+} // 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 39f07e5875..7c87f3574d 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..84fc0bbe4e 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...
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 d36a1c65c9..9c61bc1b75 100644
--- a/engines/gob/gob.cpp
+++ b/engines/gob/gob.cpp
@@ -345,8 +345,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_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/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/detection.cpp b/engines/groovie/detection.cpp
index ec401e7d24..b30c2361d2 100644
--- a/engines/groovie/detection.cpp
+++ b/engines/groovie/detection.cpp
@@ -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 6aa6c89d31..dc1d7ae73a 100644
--- a/engines/groovie/font.cpp
+++ b/engines/groovie/font.cpp
@@ -54,6 +54,7 @@ bool T7GFont::load(Common::SeekableReadStream &stream) {
if (stream.eos()) {
error("Groovie::T7GFont: Couldn't read the glyph offsets");
+ delete[] glyphOffsets;
return false;
}
diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp
index 93675b3d1e..276b26ffe7 100644
--- a/engines/groovie/groovie.cpp
+++ b/engines/groovie/groovie.cpp
@@ -110,7 +110,7 @@ Common::Error GroovieEngine::run() {
// 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);
@@ -141,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");
@@ -154,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
@@ -307,6 +307,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 437debfd17..8ae5f4157f 100644
--- a/engines/groovie/groovie.h
+++ b/engines/groovie/groovie.h
@@ -82,6 +82,8 @@ public:
GroovieEngine(OSystem *syst, const GroovieGameDescription *gd);
~GroovieEngine();
+ Common::Platform getPlatform() const;
+
protected:
// Engine APIs
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index f2b190985d..34b180a68e 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -110,6 +110,20 @@ void MusicPlayer::playCD(uint8 track) {
// Play the track starting at the requested offset (1000ms = 75 frames)
g_system->getAudioCDManager()->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 (!g_system->getAudioCDManager()->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 +399,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 +415,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 +425,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 +468,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 +695,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 +716,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 2feef9cbf7..5b5f5bd346 100644
--- a/engines/groovie/music.h
+++ b/engines/groovie/music.h
@@ -161,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/script.cpp b/engines/groovie/script.cpp
index 297da6ccc2..9fd7fa7d63 100644
--- a/engines/groovie/script.cpp
+++ b/engines/groovie/script.cpp
@@ -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 {
diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp
index 6e9359e7fc..f3e6c7c8cc 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) {}
diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h
new file mode 100644
index 0000000000..390281c356
--- /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
+ },
+ 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/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp
index 00b32425c2..abe13cec2b 100644
--- a/engines/kyra/kyra_v1.cpp
+++ b/engines/kyra/kyra_v1.cpp
@@ -105,8 +105,11 @@ Common::Error KyraEngine_v1::init() {
_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
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 +123,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);
}
diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h
index f4aab4db29..a229dc310d 100644
--- a/engines/kyra/sound_intern.h
+++ b/engines/kyra/sound_intern.h
@@ -180,6 +180,8 @@ 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;
@@ -207,6 +209,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;
diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp
index b2c8c5fb4b..7a570b3100 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"
@@ -1355,7 +1357,7 @@ public:
void setOutputLevel();
virtual void fadeStep();
- void reset();
+ virtual void reset();
const uint8 _idFlag;
@@ -1432,13 +1434,14 @@ public:
void protect();
void restore();
+ virtual void reset();
void fadeStep();
protected:
void setOutputLevel(uint8 lvl);
- bool control_f0_setInstr(uint8 para);
+ bool control_f0_setPatch(uint8 para);
bool control_f1_setTotalLevel(uint8 para);
bool control_f4_setAlgorithm(uint8 para);
bool control_f9_loadCustomPatch(uint8 para);
@@ -1458,6 +1461,7 @@ public:
~TownsPC98_OpnSfxChannel() {}
void loadData(uint8 *data);
+ void reset();
};
class TownsPC98_OpnChannelPCM : public TownsPC98_OpnChannel {
@@ -1490,9 +1494,12 @@ public:
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 updatesRegs();
+ void updateRegs();
uint8 _updateRequestBuf[64];
int _updateRequest;
@@ -1529,6 +1536,11 @@ private:
uint8 **_reg;
+ uint16 _volumeA;
+ uint16 _volumeB;
+ int _volMaskA;
+ int _volMaskB;
+
bool _ready;
};
@@ -1543,6 +1555,9 @@ public:
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;
@@ -1578,6 +1593,11 @@ private:
uint8 **_reg;
+ uint16 _volumeA;
+ uint16 _volumeB;
+ int _volMaskA;
+ int _volMaskB;
+
bool _ready;
};
@@ -1604,20 +1624,27 @@ public:
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;
+ // 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 opn 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);
@@ -1670,6 +1697,9 @@ private:
OpnTimer _timers[2];
+ int _volMaskA, _volMaskB;
+ uint16 _volumeA, _volumeB;
+
const float _baserate;
uint32 _timerbase;
@@ -1709,6 +1739,9 @@ public:
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();
@@ -1751,6 +1784,9 @@ protected:
uint8 *_sfxData;
uint16 _sfxOffsets[2];
+ uint16 _musicVolume;
+ uint16 _sfxVolume;
+
static const uint8 _drvTables[];
bool _ready;
@@ -1823,33 +1859,23 @@ void TownsPC98_OpnChannel::loadData(uint8 *data) {
_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;
+ 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];
}
}
}
@@ -2178,7 +2204,7 @@ void TownsPC98_OpnChannelSSG::init() {
#define Control(x) &TownsPC98_OpnChannelSSG::control_##x
static const ControlEventFunc ctrlEventsSSG[] = {
- Control(f0_setInstr),
+ Control(f0_setPatch),
Control(f1_setTotalLevel),
Control(f2_setKeyOffTime),
Control(f3_setFreqLSB),
@@ -2372,6 +2398,23 @@ void TownsPC98_OpnChannelSSG::setOutputLevel(uint8 lvl) {
_drv->writeReg(_part, 8 + _regOffset, _ssgTl);
}
+void TownsPC98_OpnChannelSSG::reset() {
+ TownsPC98_OpnChannel::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_OpnChannelSSG::fadeStep() {
_totalLevel--;
if ((int8)_totalLevel < 0)
@@ -2379,7 +2422,7 @@ void TownsPC98_OpnChannelSSG::fadeStep() {
setOutputLevel(_ssgStartLvl);
}
-bool TownsPC98_OpnChannelSSG::control_f0_setInstr(uint8 para) {
+bool TownsPC98_OpnChannelSSG::control_f0_setPatch(uint8 para) {
_instr = para << 4;
para = (para >> 3) & 0x1e;
if (para)
@@ -2463,6 +2506,39 @@ void TownsPC98_OpnSfxChannel::loadData(uint8 *data) {
_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_OpnSfxChannel::reset() {
+ TownsPC98_OpnChannel::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_OpnChannelPCM::TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs,
@@ -2557,7 +2633,8 @@ bool TownsPC98_OpnChannelPCM::control_ff_endOfTrack(uint8 para) {
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) {
+ _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));
@@ -2705,24 +2782,30 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) {
}
}
_pReslt = _evpTimer ^ _attack;
- updatesRegs();
+ updateRegs();
}
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];
+ 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;
+ finOut /= 3;
+
buffer[i << 1] += finOut;
buffer[(i << 1) + 1] += finOut;
}
}
-void TownsPC98_OpnSquareSineSource::updatesRegs() {
+void TownsPC98_OpnSquareSineSource::updateRegs() {
for (int i = 0; i < _updateRequest;) {
uint8 b = _updateRequestBuf[i++];
uint8 a = _updateRequestBuf[i++];
@@ -2732,7 +2815,7 @@ void TownsPC98_OpnSquareSineSource::updatesRegs() {
}
TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const uint32 timerbase) :
- _tickLength(timerbase * 2), _timer(0), _ready(false) {
+ _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];
@@ -2891,6 +2974,12 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) {
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;
}
@@ -2927,6 +3016,7 @@ TownsPC98_OpnCore::TownsPC98_OpnCore(Audio::Mixer *mixer, OpnType type) :
_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()),
+ _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255),
_regProtectionFlag(false), _ready(false) {
memset(&_timers[0], 0, sizeof(OpnTimer));
@@ -2977,7 +3067,7 @@ bool TownsPC98_OpnCore::init() {
_prc->init(_percussionData);
}
- _mixer->playStream(Audio::Mixer::kMusicSoundType,
+ _mixer->playStream(Audio::Mixer::kPlainSoundType,
&_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true);
_ready = true;
@@ -2989,7 +3079,7 @@ 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);
+ memset(_chanInternal[i].feedbuf, 0, 3);
_chanInternal[i].algorithm = 0;
_chanInternal[i].frqTemp = 0;
_chanInternal[i].enableLeft = _chanInternal[i].enableRight = true;
@@ -3228,6 +3318,26 @@ int TownsPC98_OpnCore::readBuffer(int16 *buffer, const int numSamples) {
return numSamples;
}
+void TownsPC98_OpnCore::setVolumeIntern(int volA, int volB) {
+ Common::StackLock lock(_mutex);
+ _volumeA = volA;
+ _volumeB = volB;
+ if (_ssg)
+ _ssg->setVolumeIntern(volA, volB);
+ if (_prc)
+ _prc->setVolumeIntern(volA, volB);
+}
+
+void TownsPC98_OpnCore::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_OpnCore::generateTables() {
delete[] _oprRates;
_oprRates = new uint8[128];
@@ -3388,6 +3498,12 @@ void TownsPC98_OpnCore::nextTick(int32 *buffer, uint32 bufferSize) {
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;
@@ -3408,11 +3524,14 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : To
_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),
+ _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;
}
@@ -3450,6 +3569,8 @@ bool TownsPC98_OpnDriver::init() {
TownsPC98_OpnCore::init();
+ setVolumeChannelMasks(-1, 0);
+
_channels = new TownsPC98_OpnChannel *[_numChan];
for (int i = 0; i < _numChan; i++) {
int ii = i * 6;
@@ -3664,8 +3785,11 @@ void TownsPC98_OpnDriver::timerCallbackA() {
_trackPtr = _musicBuffer;
}
- if (_finishedSfxFlag == _updateSfxFlag)
+ if (_updateSfxFlag && _finishedSfxFlag == _updateSfxFlag) {
_sfxPlaying = false;
+ _updateSfxFlag = 0;
+ setVolumeChannelMasks(-1, 0);
+ }
}
void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) {
@@ -3680,14 +3804,22 @@ void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) {
}
void TownsPC98_OpnDriver::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;
}
@@ -4048,7 +4180,9 @@ SoundPC98::~SoundPC98() {
bool SoundPC98::init() {
_driver = new TownsPC98_OpnDriver(_mixer, TownsPC98_OpnDriver::OD_TYPE26);
- return _driver->init();
+ bool reslt = _driver->init();
+ updateVolumeSettings();
+ return reslt;
}
void SoundPC98::loadSoundFile(uint file) {
@@ -4121,6 +4255,13 @@ void SoundPC98::playSoundEffect(uint8 track) {
_driver->loadSoundEffectData(_sfxTrackData, track);
}
+void SoundPC98::updateVolumeSettings() {
+ if (!_driver)
+ return;
+
+ _driver->setMusicVolume(ConfMan.getInt("music_volume"));
+ _driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume"));
+}
// KYRA 2
@@ -4159,7 +4300,9 @@ bool SoundTownsPC98_v2::init() {
_useFmSfx = true;
}
- return _driver->init();
+ bool reslt = _driver->init();
+ updateVolumeSettings();
+ return reslt;
}
void SoundTownsPC98_v2::loadSoundFile(Common::String file) {
@@ -4314,6 +4457,14 @@ void SoundTownsPC98_v2::playSoundEffect(uint8 track) {
_driver->loadSoundEffectData(_sfxTrackData, track);
}
+void SoundTownsPC98_v2::updateVolumeSettings() {
+ if (!_driver)
+ return;
+
+ _driver->setMusicVolume(ConfMan.getInt("music_volume"));
+ _driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume"));
+}
+
// static resources
const uint32 TownsPC98_OpnCore::_adtStat[] = {
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/sound.cpp b/engines/lure/sound.cpp
index e725b7c31a..cd539dfab4 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);
diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp
index 1142ba48d1..0ead57aac9 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;
}
/**
@@ -259,7 +288,7 @@ void MadsAnimation::load(const Common::String &filename, int abortTimers) {
_abortMode = _madsVm->scene()->_abortTimersMode2;
for (int i = 0; i < 3; ++i)
- _actionNouns[i] = _madsVm->scene()->actionNouns[i];
+ _actionNouns[i] = _madsVm->globals()->actionNouns[i];
// 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;
}
}
@@ -424,7 +465,7 @@ void MadsAnimation::update() {
if (_abortMode != ABORTMODE_1) {
// Copy the noun list
for (int i = 0; i < 3; ++i)
- _madsVm->scene()->actionNouns[i] = _actionNouns[i];
+ _madsVm->globals()->actionNouns[i] = _actionNouns[i];
}
}
}
@@ -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..583d829066 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,29 @@ private:
int _unkIndex;
Common::Point _unkList[2];
uint32 _nextFrameTimer;
+ uint32 _nextScrollTimer;
int _messageCtr;
int _abortTimers;
AbortTimerMode _abortMode;
uint16 _actionNouns[3];
+
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..19fbf6e852 100644
--- a/engines/m4/console.cpp
+++ b/engines/m4/console.cpp
@@ -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());
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..c10ea6c9f6 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,38 +410,35 @@ 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
@@ -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))
+ *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/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/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..e451a306ef 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) {
@@ -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();
}
@@ -192,7 +359,7 @@ void MadsSceneLogic::enterScene() {
_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);
+ _madsVm->scene()->_sequenceList.addSubEntry(_spriteIndexes[17], SM_FRAME_INDEX, 7, 70);
_spriteIndexes[18] = startReversibleSpriteSequence(_spriteIndexes[3], 0, 10, 0, 0, 60);
_spriteIndexes[19] = startCycledSpriteSequence(_spriteIndexes[4], 0, 5, 0, 1, 0);
@@ -208,15 +375,15 @@ 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);
@@ -235,13 +402,19 @@ void MadsSceneLogic::enterScene() {
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->_player._playerPos = Common::Point(68, 140);
+ _madsVm->_player._direction = 4;
+ _madsVm->_player._visible = false;
+ _madsVm->_player._stepEnabled = false;
- _madsVm->scene()->getSceneResources().playerPos = Common::Point(68, 140);
- _madsVm->scene()->getSceneResources().playerDir = 4;
- // TODO: Flags setting
+ dataMap()[0x56FC] = 0;
+ dataMap()[0x5482] = 0;
+ dataMap()[0x5484] = 30;
}
+ _madsVm->globals()->_dataMap[0x5486] = 0;
lowRoomsEntrySound();
}
@@ -250,14 +423,66 @@ void MadsSceneLogic::doAction() {
}
void MadsSceneLogic::sceneStep() {
- // FIXME: Temporary code to display a message on-screen
- static bool tempBool = false;
- if (!tempBool) {
- tempBool = true;
-
- _madsVm->scene()->_kernelMessages.add(Common::Point(63, 100), 0x1110, 0, 0, 240,
- _madsVm->globals()->getQuote(49));
+ // 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..98d6df6163 100644
--- a/engines/m4/mads_logic.h
+++ b/engines/m4/mads_logic.h
@@ -42,6 +42,8 @@ private:
uint16 startSpriteSequence3(uint16 srcSpriteIdx, int v0, 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,6 +52,8 @@ private:
const char *formAnimName(char sepChar, int16 suffixNum);
void getSceneSpriteSet();
void getAnimName();
+
+ IntStorage &dataMap();
public:
void selectScene(int sceneNum);
@@ -59,6 +63,11 @@ public:
void sceneStep();
};
+class MadsGameLogic {
+public:
+ static void initialiseGlobals();
+};
+
}
#endif
diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp
index 94894e78be..d7d9cf4150 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();
}
diff --git a/engines/m4/mads_player.cpp b/engines/m4/mads_player.cpp
new file mode 100644
index 0000000000..8531a3ed44
--- /dev/null
+++ b/engines/m4/mads_player.cpp
@@ -0,0 +1,454 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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);
+ _direction = 0;
+ _newDirection = 0;
+ _forceRefresh = true;
+ _stepEnabled = true;
+ _ticksAmount = 3;
+ _priorTimer = 0;
+ _visible = true;
+ _priorVisible = false;
+ _visible3 = false;
+ _yScale = 0;
+ _moving = false;
+ _spriteListStart = 0;
+ _spriteListIdx = 0;
+ _spritesChanged = true;
+ _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;
+ 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().depthTable[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 word_844c0 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();
+ }
+}
+
+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() {
+ // TODO: Handle player movement
+}
+
+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;
+}
+
+} // End of namespace M4
diff --git a/engines/m4/mads_player.h b/engines/m4/mads_player.h
new file mode 100644
index 0000000000..65ed9ef89c
--- /dev/null
+++ b/engines/m4/mads_player.h
@@ -0,0 +1,88 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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"
+
+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();
+public:
+ char _spritesPrefix[16];
+ int _spriteSetCount;
+ bool _spriteSetsPresent[8];
+ Common::Point _playerPos;
+ Common::Point _destPos;
+ 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;
+
+ static const int _directionListIndexes[32];
+public:
+ MadsPlayer();
+
+ bool loadSprites(const char *prefix);
+ void update();
+ void updateFrame();
+ void setupFrame();
+ void step();
+ void nextFrame();
+};
+
+} // End of namespace M4
+
+#endif
diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp
index a65224c722..e4f84aeb5a 100644
--- a/engines/m4/mads_scene.cpp
+++ b/engines/m4/mads_scene.cpp
@@ -55,8 +55,6 @@ 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;
}
MadsScene::~MadsScene() {
@@ -69,8 +67,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 +117,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();
@@ -236,12 +268,14 @@ void MadsScene::leftClick(int x, int y) {
}
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) {
@@ -298,9 +332,20 @@ void MadsScene::update() {
}
void MadsScene::updateState() {
+ _madsVm->_player.update();
+
+ // Step through the scene
_sceneLogic.sceneStep();
- _sequenceList.tick();
+ _madsVm->_player.step();
+ _madsVm->_player._unk3 = 0;
+
+ if (_abortTimersMode == ABORTMODE_1)
+ _abortTimers = 0;
+
+ // Handle updating the player frame
+ _madsVm->_player.nextFrame();
+
if ((_activeAnimation) && !_abortTimers) {
_activeAnimation->update();
if (((MadsAnimation *) _activeAnimation)->freeFlag()) {
@@ -309,9 +354,37 @@ void MadsScene::updateState() {
}
}
- _kernelMessages.update();
+ MadsView::update();
+
+ // Remove the animation if it's been completed
+ if ((_activeAnimation) && ((MadsAnimation *)_activeAnimation)->freeFlag())
+ freeAnimation();
}
+/**
+ * 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();
+ }
+
+ delete _activeAnimation;
+ _activeAnimation = NULL;
+}
+
+
int MadsScene::loadSceneSpriteSet(const char *setName) {
char resName[100];
strcpy(resName, setName);
@@ -323,27 +396,6 @@ int MadsScene::loadSceneSpriteSet(const char *setName) {
return _spriteSlots.addSprites(resName);
}
-void MadsScene::loadPlayerSprites(const char *prefix) {
- const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' };
- char setName[80];
-
- strcpy(setName, "*");
- strcat(setName, prefix);
- strcat(setName, "_0.SS");
- char *digitP = strchr(setName, '_') + 1;
-
- for (int idx = 0; idx < 8; ++idx) {
- *digitP = suffixList[idx];
-
- if (_vm->res()->resourceExists(setName)) {
- loadSceneSpriteSet(setName);
- return;
- }
- }
-
- error("Couldn't find player sprites");
-}
-
enum boxSprites {
topLeft = 0,
topRight = 1,
@@ -442,12 +494,12 @@ 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;
}
@@ -637,7 +689,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,25 +701,41 @@ 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);
+ _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;
rec.load(stream);
- objects.push_back(rec);
+ _objects.push_back(rec);
}
for (int i = 0; i < 20 - objectCount; ++i)
stream->skip(48);
@@ -677,25 +745,25 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su
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 +776,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)
@@ -915,7 +996,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
@@ -1111,9 +1192,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..e671dfb194 100644
--- a/engines/m4/mads_scene.h
+++ b/engines/m4/mads_scene.h
@@ -35,22 +35,26 @@ namespace M4 {
#define INTERFACE_HEIGHT 106
class MadsInterfaceView;
+#define DEPTH_BANDS_SIZE 15
+
class MadsSceneResources: public SceneResources {
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; }
+ int _sceneId;
+ int _artFileNum;
+ int _depthStyle;
+ int _width;
+ int _height;
+ Common::Array<MadsObject> _objects;
+ 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; }
};
enum MadsActionMode {ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, ACTMODE_TALK = 6};
@@ -99,7 +103,7 @@ private:
SpriteAsset *_playerSprites;
void drawElements();
- void loadScene2(const char *aaName);
+ void loadScene2(const char *aaName, int sceneNumber);
void loadSceneTemporary();
void loadSceneHotspots(int sceneNumber);
void clearAction();
@@ -107,7 +111,6 @@ private:
void setAction();
public:
char _aaName[100];
- uint16 actionNouns[3];
public:
MadsScene(MadsEngine *vm);
virtual ~MadsScene();
@@ -126,9 +129,10 @@ 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; }
diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp
index c7b4f76a00..d7e6435b14 100644
--- a/engines/m4/mads_views.cpp
+++ b/engines/m4/mads_views.cpp
@@ -86,10 +86,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 +105,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 +148,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 +168,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,7 +185,7 @@ 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
@@ -192,14 +207,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 +235,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 +298,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 +336,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 +355,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 +424,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 +450,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 +524,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 +545,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 {
@@ -732,9 +753,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 +770,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 +842,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 +882,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) {
@@ -937,7 +974,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;
}
@@ -1174,25 +1211,29 @@ MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceL
_kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*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 +1243,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 +1251,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 +1263,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..0604ae1ee1 100644
--- a/engines/m4/mads_views.h
+++ b/engines/m4/mads_views.h
@@ -92,13 +92,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 +140,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 +149,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 +171,10 @@ public:
AbortTimerMode abortMode;
uint16 actionNouns[3];
char msg[100];
+
+ MadsKernelMessageEntry() {
+ flags = 0;
+ }
};
class MadsKernelMessageList {
@@ -289,7 +294,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};
@@ -367,10 +373,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;
};
@@ -388,7 +395,6 @@ public:
MadsDirtyAreas _dirtyAreas;
int _textSpacing;
- int _ticksAmount;
uint32 _newTimeout;
int _abortTimers;
int8 _abortTimers2;
@@ -398,12 +404,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/scene.cpp b/engines/m4/scene.cpp
index 15c68f276c..e78d7f865e 100644
--- a/engines/m4/scene.cpp
+++ b/engines/m4/scene.cpp
@@ -55,6 +55,7 @@ Scene::Scene(MadsM4Engine *vm, SceneResources *res): View(vm, Common::Rect(0, 0,
Scene::~Scene() {
leaveScene();
+ _vm->_scene = NULL;
}
void Scene::loadScene(int sceneNumber) {
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/detection.cpp b/engines/made/detection.cpp
index 1dfc0c3f83..dd2becd3b8 100644
--- a/engines/made/detection.cpp
+++ b/engines/made/detection.cpp
@@ -493,7 +493,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 917141ae04..20b4dc1e1b 100644
--- a/engines/made/made.cpp
+++ b/engines/made/made.cpp
@@ -96,11 +96,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/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/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..6d3f6f0b04 100644
--- a/engines/parallaction/input.cpp
+++ b/engines/parallaction/input.cpp
@@ -395,7 +395,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 +412,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/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..8b7654d689 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,86 @@ 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();
+ }
+ 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 +176,11 @@ 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);
+ _driver->close();
+ delete _driver;
+ _parser->setMidiDriver(NULL);
+ delete _parser;
free(_songTable);
free(_midiMusicData);
@@ -194,6 +190,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 +211,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 +228,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 +254,8 @@ void Music::play(uint32 resourceId, MusicFlags flags) {
}
_trackNumber = resourceId;
- _player->stopMusic();
_mixer->stopHandle(_musicHandle);
+ _parser->unloadMusic();
int realTrackNumber;
@@ -356,55 +356,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 +377,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 131078a9c3..f3b0f177b0 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..d1ab3bc9d7 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;
@@ -433,7 +419,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.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 814fbff636..33aa5514f2 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) {
// 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));
@@ -106,6 +102,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 +148,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));
@@ -171,8 +170,10 @@ Console::Console(SciEngine *engine) : GUI::Debugger() {
// 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("bc", 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));
@@ -180,48 +181,42 @@ Console::Console(SciEngine *engine) : GUI::Debugger() {
// 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);
}
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 +238,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 +254,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);
}
@@ -274,14 +272,6 @@ void Console::postEnter() {
}
}
-
-#if 0
-// Unused
-#define LOOKUP_SPECIES(species) (\
- (species >= 1000) ? species : *(s->_classTable[species].scriptposp) \
- + s->_classTable[species].class_offset)
-#endif
-
bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf("\n");
DebugPrintf("Variables\n");
@@ -326,6 +316,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,11 +361,11 @@ 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");
@@ -383,15 +374,15 @@ bool Console::cmdHelp(int argc, const char **argv) {
DebugPrintf(" go - Executes the script\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_list / bplist / bl - Lists the current breakpoints\n");
+ DebugPrintf(" bp_del / bpdel / bc - 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("\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 +405,12 @@ 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;
- DebugPrintf("Game ID: %s\n", _engine->getGameID());
+ DebugPrintf("Game ID: %s\n", _engine->getGameIdStr());
DebugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion()));
DebugPrintf("\n");
DebugPrintf("Detected features:\n");
@@ -434,9 +418,10 @@ 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");
@@ -482,14 +467,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;
}
@@ -597,7 +582,7 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) {
bool Console::cmdRegisters(int argc, const char **argv) {
EngineState *s = _engine->_gamestate;
DebugPrintf("Current register values:\n");
- DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->restAdjustCur);
+ DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->restAdjust);
if (!s->_executionStack.empty()) {
DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n",
@@ -820,7 +805,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,15 +814,15 @@ 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;
}
@@ -847,6 +832,167 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) {
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");
+ }
+
+ return true;
+}
+
bool Console::cmdList(int argc, const char **argv) {
if (argc < 2) {
DebugPrintf("Lists all the resources of a given type\n");
@@ -870,19 +1016,19 @@ 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");
}
@@ -920,7 +1066,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();
@@ -957,8 +1103,7 @@ bool Console::cmdRestoreGame(int argc, const char **argv) {
}
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;
}
@@ -1135,7 +1280,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
@@ -1217,7 +1366,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,10 +1401,16 @@ 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());
break;
@@ -1281,9 +1436,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 +1549,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 +1572,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 +1580,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 +1597,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;
}
@@ -1473,23 +1636,7 @@ bool Console::cmdShowMap(int argc, const char **argv) {
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 +1656,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,7 +1675,7 @@ bool Console::cmdStartSound(int argc, const char **argv) {
return true;
}
- _engine->_gamestate->_soundCmd->startNewSound(number);
+ g_sci->_soundCmd->startNewSound(number);
return false;
}
@@ -1552,37 +1699,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 +1727,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 +1750,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 +1761,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 +1773,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 +1796,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 +1828,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 +1873,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 +1883,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 +2021,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 +2100,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 +2116,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 +2230,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 +2246,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 +2283,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,33 +2299,39 @@ 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 false;
+}
+
+bool Console::cmdStepOver(int argc, const char **argv) {
+ _debugState.seeking = kDebugSeekStepOver;
+ _debugState.seekLevel = _engine->_gamestate->_executionStack.size();
+ _debugState.debugging = true;
return false;
}
bool Console::cmdStepEvent(int argc, const char **argv) {
- g_debugState.stopOnEvent = true;
- g_debugState.debugging = true;
+ _debugState.stopOnEvent = true;
+ _debugState.debugging = true;
return false;
}
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;
}
@@ -2209,9 +2343,9 @@ 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;
}
@@ -2239,12 +2373,12 @@ 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;
}
@@ -2357,11 +2491,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 +2505,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;
}
@@ -2426,7 +2560,7 @@ 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);
}
@@ -2437,8 +2571,8 @@ bool Console::cmdBreakpointList(int argc, const char **argv) {
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 +2588,9 @@ bool Console::cmdBreakpointList(int argc, const char **argv) {
i++;
}
+ if (!i)
+ DebugPrintf(" No breakpoints defined.\n");
+
return true;
}
@@ -2461,14 +2598,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,15 +2623,15 @@ 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;
}
@@ -2509,8 +2653,8 @@ 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;
}
@@ -2530,8 +2674,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,9 +2875,9 @@ 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
@@ -2980,8 +3124,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 +3215,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 +3283,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 +3302,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() >> 8;
+ if (c < 32 || c >= 127)
+ c = '.';
+ printf("%c", c);
+ c = data[i].toUint16() & 0xff;
+ 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() >> 8;
+ if (c < 32 || c >= 127)
+ c = '.';
+ printf("%c", c);
+ c = data[i].toUint16() & 0xff;
+ 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..51f02d7168 100644
--- a/engines/sci/console.h
+++ b/engines/sci/console.h
@@ -74,6 +74,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 +118,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);
@@ -145,12 +146,18 @@ 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;
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..eb2c989e0d 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 =========================================================
@@ -106,6 +105,7 @@ 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!"},
{"phantasmagoria", "Phantasmagoria"},
{"pqswat", "Police Quest: SWAT"},
{"shivers", "Shivers"},
@@ -120,6 +120,81 @@ 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 },
+ { "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 },
+ { "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 +273,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();
@@ -295,7 +376,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 +386,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 {
@@ -419,7 +504,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
@@ -509,12 +599,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 {
@@ -652,7 +746,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 +762,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..aa1e26e0f4 100644
--- a/engines/sci/detection_tables.h
+++ b/engines/sci/detection_tables.h
@@ -753,14 +753,31 @@ static const struct ADGameDescription SciGameDescriptions[] = {
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},
+ {NULL, 0, NULL, 0}},
+ 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}},
Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH },
- // Jones in the Fast Lane - English DOS
+ // Jones in the Fast Lane EGA - English DOS
+ // SCI interpreter version 1.000.172 (not 100% sure FIXME)
+ {"jones", "", {
+ {"resource.map", 0, "be4cf9e8c1e253623ef35ae3b8a1d998", 1800},
+ {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 202105},
+ {"resource.002", 0, "b86daa3ba2784d1502da881eedb80d9b", 341771},
+ {NULL, 0, NULL, 0}},
+ 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},
@@ -1667,7 +1684,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
#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}},
@@ -1675,7 +1692,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
// 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}},
@@ -1683,7 +1700,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
// 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}},
@@ -2390,7 +2407,7 @@ static const struct ADGameDescription SciGameDescriptions[] = {
},
// 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},
@@ -2407,27 +2424,6 @@ static const struct ADGameDescription SciGameDescriptions[] = {
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
-
- // 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
@@ -2572,6 +2568,18 @@ static const struct ADGameDescription SciGameDescriptions[] = {
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},
+ {NULL, 0, NULL, 0}},
+ 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", {
@@ -2660,6 +2668,15 @@ static const struct ADGameDescription SciGameDescriptions[] = {
{NULL, 0, NULL, 0}},
Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH },
+ // 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},
+ {NULL, 0, NULL, 0}},
+ Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_NOSPEECH },
+
// Space Quest 3 - German DOS (from Tobis87)
// SCI interpreter version 0.000.453 (?)
{"sq3", "", {
diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp
index 48f7c2d64f..fee6e69da7 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"
@@ -51,13 +52,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 +70,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 +84,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 +105,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 +119,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 +137,10 @@ 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) {
+ } 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 +173,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 +192,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
@@ -219,7 +225,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
@@ -293,7 +299,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 +311,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 +323,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 +349,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 +389,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;
}
}
@@ -395,8 +405,20 @@ SciVersion GameFeatures::detectGfxFunctionsType() {
#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 +430,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 +441,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 +472,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 +485,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 +515,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..5b383746d8 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);
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..beb1d3ce35 100644
--- a/engines/sci/engine/kernel.cpp
+++ b/engines/sci/engine/kernel.cpp
@@ -33,10 +33,28 @@
namespace Sci {
-// Default kernel name table
-#define SCI_KNAMES_DEFAULT_ENTRIES_NR 0x89
-
-static const char *sci_default_knames[SCI_KNAMES_DEFAULT_ENTRIES_NR] = {
+// Uncompiled kernel signatures are formed from a string of letters.
+// each corresponding to a type of a parameter (see below).
+// 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
+#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')
+
+
+
+/** Default kernel name table. */
+static const char *s_defaultKernelNames[] = {
/*0x00*/ "Load",
/*0x01*/ "UnLoad",
/*0x02*/ "ScriptID",
@@ -152,18 +170,18 @@ static const char *sci_default_knames[SCI_KNAMES_DEFAULT_ENTRIES_NR] = {
/*0x6c*/ "Graph",
/*0x6d*/ "Joystick",
// End of kernel function table for SCI0
- /*0x6e*/ "ShiftScreen",
+ /*0x6e*/ "Dummy", // ShiftScreen
/*0x6f*/ "Palette",
/*0x70*/ "MemorySegment",
/*0x71*/ "Intersections", // MoveCursor (SCI1 late), PalVary (SCI1.1)
/*0x72*/ "Memory",
- /*0x73*/ "ListOps",
+ /*0x73*/ "Dummy", // ListOps
/*0x74*/ "FileIO",
/*0x75*/ "DoAudio",
/*0x76*/ "DoSync",
/*0x77*/ "AvoidPath",
/*0x78*/ "Sort", // StrSplit (SCI01)
- /*0x79*/ "ATan",
+ /*0x79*/ "Dummy", // ATan
/*0x7a*/ "Lock",
/*0x7b*/ "StrSplit",
/*0x7c*/ "GetMessage", // Message (SCI1.1)
@@ -181,227 +199,456 @@ static const char *sci_default_knames[SCI_KNAMES_DEFAULT_ENTRIES_NR] = {
/*0x88*/ "Dummy" // DbugStr
};
-struct SciKernelFunction {
+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");
+}
+
+// [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)
+
+// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
+static const SciWorkaroundEntry kAbs_workarounds[] = {
+ { GID_HOYLE1, 1, 0, "room1", "doit", -1, 0, { 2, 0x3e9 } }, // crazy eights - called with objects instead of integers
+ { GID_HOYLE1, 2, 0, "room2", "doit", -1, 0, { 2, 0x3e9 } }, // old maid - called with objects instead of integers
+ { GID_HOYLE1, 3, 0, "room3", "doit", -1, 0, { 2, 0x3e9 } }, // hearts - called with objects instead of integers
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
+static const SciWorkaroundEntry kDisposeScript_workarounds[] = {
+ { GID_QFG1, 64, 0, "rm64", "dispose", -1, 0, { 1, 0 } }, // when leaving graveyard, parameter 0 is an object
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
+static const SciWorkaroundEntry kDoSoundFade_workarounds[] = {
+ { GID_KQ6, 989, 0, "globalSound", "fade", -1, 0, { 0, 0 } }, // during intro, parameter 4 is an object
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
+static const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = {
+ { GID_LSL6, 85, 0, "rScroller", "hide", -1, 0, { 0, 0 } }, // happens when restoring (sometimes), same as the one below
+ { GID_LSL6, 85, 0, "lScroller", "hide", -1, 0, { 0, 0 } }, // happens when restoring (sometimes), same as the one below
+ { GID_LSL6, 86, 0, "LL6Inv", "show", -1, 0, { 0, 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, 86, 0, "LL6Inv", "hide", -1, 0, { 0, 0 } }, // happens during the game, gets called with 1 extra parameter
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
+static const SciWorkaroundEntry kGraphFillBoxForeground_workarounds[] = {
+ { GID_LSL6, 0, 0, "LSL6", "hideControls", -1, 0, { 0, 0 } }, // happens when giving the bungee key to merrily - gets called with additional 5th parameter
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
+static const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = {
+ { GID_SQ4, 818, 0, "iconTextSwitch", "show", -1, 0, { 0, 0 } }, // game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
+static const SciWorkaroundEntry kUnLoad_workarounds[] = {
+ { GID_LSL6, 130, 0, "recruitLarryScr", "changeState", -1, 0, { 1, 0 } }, // during intro, a 3rd parameter is passed by accident
+ { GID_LSL6, 740, 0, "showCartoon", "changeState", -1, 0, { 1, 0 } }, // during ending, 4 additional parameters are passed by accident
+ { GID_SQ1, 303, 0, "slotGuy", "dispose", -1, 0, { 1, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+struct SciKernelMapSubEntry {
+ SciVersion fromVersion;
+ SciVersion toVersion;
+
+ uint16 id;
+
const char *name;
- KernelFunc *fun; /* The actual function */
- const char *signature; /* kfunct signature */
+ 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_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 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(DoSoundDummy), "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(DoSoundResume), "", NULL },
+ { SIG_SOUNDSCI0, 8, MAP_CALL(DoSoundMasterVolume), "(i)", NULL },
+ { SIG_SOUNDSCI0, 9, MAP_CALL(DoSoundUpdate), "o", NULL },
+ { SIG_SOUNDSCI0, 10, MAP_CALL(DoSoundFade), "o", NULL },
+ { 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(DoSoundDummy), 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 },
+ { SIG_SOUNDSCI1EARLY, 8, MAP_CALL(DoSoundStop), NULL, NULL },
+ { SIG_SOUNDSCI1EARLY, 9, MAP_CALL(DoSoundPause), "[o0]i", NULL },
+ { SIG_SOUNDSCI1EARLY, 10, MAP_CALL(DoSoundFade), "oiiii", NULL },
+ { SIG_SOUNDSCI1EARLY, 11, MAP_CALL(DoSoundUpdateCues), "o", NULL },
+ { SIG_SOUNDSCI1EARLY, 12, MAP_CALL(DoSoundSendMidi), "oiiii", NULL },
+ { SIG_SOUNDSCI1EARLY, 13, MAP_CALL(DoSoundReverb), "oi", 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(DoSoundDummy), "", 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), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 19, MAP_CALL(DoSoundReverb), NULL, NULL },
+ { SIG_SOUNDSCI1LATE, 20, MAP_CALL(DoSoundUpdate), NULL, NULL },
+ SCI_SUBOPENTRY_TERMINATOR
};
-#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, ".*"),
+// 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)", NULL },
+ // 5 - nop
+ // 6 - draw pattern
+ { SIG_SCIALL, 7, MAP_CALL(GraphSaveBox), "iiiii", NULL },
+ { 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)", NULL }, // kq6 hires
+ { SIG_SCIALL, 12, MAP_CALL(GraphUpdateBox), "iiii(i)", NULL },
+ { SIG_SCIALL, 13, MAP_CALL(GraphRedrawBox), "iiii", NULL },
+ { SIG_SCIALL, 14, MAP_CALL(GraphAdjustPriority), "ii", NULL },
+ { SIG_SCI11, 15, MAP_CALL(GraphSaveUpscaledHiresBox), "iiii", NULL }, // kq6 hires
+ SCI_SUBOPENTRY_TERMINATOR
+};
-#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...
+// version, subId, function-mapping, signature, workarounds
+static const SciKernelMapSubEntry kPalVary_subops[] = {
+ { 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), "", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
-#endif
+// 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", NULL },
+ { 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), "i", NULL },
+ SCI_SUBOPENTRY_TERMINATOR
+};
- // 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
+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 },
+ { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL },
+ { MAP_CALL(CelHigh), SIG_EVERYWHERE, "ii(i)", NULL, NULL },
+ { MAP_CALL(CelWide), SIG_EVERYWHERE, "ii(i)", NULL, NULL },
+ { MAP_CALL(CheckFreeSpace), SIG_SCI32, SIGFOR_ALL, "r.*", 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, NULL }, // 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([io])(i)(ii[io])(i)", kDoSound_subops, NULL },
+ { MAP_CALL(DoSync), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop
+ { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiii(i)(i)(r0)", NULL, NULL }, // 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(.*)", NULL, NULL }, // subop
+ { MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL, NULL },
+ { 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, NULL },
+ // ^^ FIXME - occasionally KQ6 passes a 5th argument by mistake
+ { 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, NULL },
+ { 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, NULL }, // 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, NULL },
+ { 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, "ii", 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_EVERYWHERE, "i(i*)", NULL, NULL },
+ { 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(iii)(i)(i)(i)", NULL, NULL },
+ { 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, NULL },
+ { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, NULL },
+ { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rr(i)", NULL, NULL },
+ { MAP_CALL(StrCpy), SIG_EVERYWHERE, "[r0]r(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_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 },
- {NULL, NULL, NULL} // Terminator
+#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_EVERYWHERE, "(.*)", NULL, 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 },
+ { NULL, NULL, SIG_EVERYWHERE, NULL, NULL, NULL }
+#endif
};
-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 i = _kernelFuncs.begin(); i != _kernelFuncs.end(); ++i)
+ free(i->signature);
}
uint Kernel::getSelectorNamesSize() const {
@@ -409,6 +656,8 @@ uint Kernel::getSelectorNamesSize() const {
}
const Common::String &Kernel::getSelectorName(uint selector) const {
+ if (selector >= _selectorNames.size())
+ return _invalid;
return _selectorNames[selector];
}
@@ -417,12 +666,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 +724,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;
+ 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++;
}
- 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;
+ 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;
+ }
+ }
}
-
- // Don't map dummy functions - they will never be called
- if (sought_name == "Dummy") {
- _kernelFuncs[functnr].isDummy = true;
- continue;
+ 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);
- // 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;
- }
- }
- } // for all functions requesting to be mapped
+ // Write terminator
+ *writePos = 0;
- debugC(2, kDebugLevelVM, "Handled %d/%d kernel functions, mapping %d and ignoring %d.",
- mapped + ignored, _kernelNames.size(), mapped, ignored);
-
- 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,54 +968,286 @@ 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 & KSIG_ELLIPSIS))
- ++sig;
- ++argv;
- --argc;
+ 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++;
+ }
+ 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 (!((type & ~SIG_IS_INVALID) & curSig))
+ return false; // type mismatch
- if (argc) {
- warning("kernel_matches_signature: too many arguments");
- return false; // Too many arguments
+ 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].debugCalls = 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;
+}
+
+void Kernel::setDefaultKernelNames() {
+ _kernelNames = Common::StringArray(s_defaultKernelNames, ARRAYSIZE(s_defaultKernelNames));
// Some (later) SCI versions replaced CanBeHere by CantBeHere
if (_selectorCache.cantBeHere != -1)
@@ -727,14 +1282,19 @@ 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";
@@ -747,20 +1307,19 @@ void Kernel::setDefaultKernelNames(Common::String gameId) {
}
}
-bool Kernel::loadKernelNames(Common::String gameId) {
+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();
mapFunctions();
- return true;
}
Common::String Kernel::lookupText(reg_t address, int index) {
@@ -769,31 +1328,28 @@ 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;
}
} // End of namespace Sci
diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h
index 8f8f34f74e..fa206e8053 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,7 @@ namespace Sci {
struct Node; // from segment.h
struct List; // from segment.h
+struct SelectorCache; // from selector.h
/**
* @defgroup VocabularyResources Vocabulary resources in SCI
@@ -92,59 +93,67 @@ 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 comparsion
+ 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 comparsion
+ 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);
+typedef reg_t KernelFunctionCall(EngineState *s, int argc, reg_t *argv);
+
+struct SciWorkaroundEntry {
+ SciGameId gameId;
+ int scriptNr;
+ int16 inheritanceLevel;
+ const char *objectName;
+ const char *methodName;
+ int localCallOffset;
+ int index;
+ reg_t newValue;
+};
+
+#define SCI_WORKAROUNDENTRY_TERMINATOR { (SciGameId)0, -1, 0, NULL, NULL, -1, 0, { 0, 0 } }
-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;
+struct KernelSubFunction {
+ KernelFunctionCall *function;
+ const char *name;
+ uint16 *signature;
+ const SciWorkaroundEntry *workarounds;
};
-enum AutoDetectedFeatures {
- kFeatureOldScriptHeader = 1 << 0
+struct KernelFunction {
+ KernelFunctionCall *function;
+ const char *name;
+ uint16 *signature;
+ const SciWorkaroundEntry *workarounds;
+ const KernelSubFunction *subFunctions;
+ uint16 subFunctionCount;
+ bool debugCalls;
};
class Kernel {
public:
/**
- * Initializes the SCI kernel
+ * Initializes the SCI kernel.
*/
Kernel(ResourceManager *resMan, SegManager *segMan);
~Kernel();
@@ -156,18 +165,7 @@ public:
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 +176,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 +202,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 +218,32 @@ 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);
+
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();
#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 +258,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 +423,7 @@ 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 kEmpty(EngineState *s, int argc, reg_t *argv);
#ifdef ENABLE_SCI32
// SCI2 Kernel Functions
@@ -430,6 +431,7 @@ 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);
// "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,12 +453,69 @@ 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);
#endif
+reg_t kDoSoundInit(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundPlay(EngineState *s, int argc, reg_t *argv);
+reg_t kDoSoundDummy(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 kDoSoundResume(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 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);
+
//@}
} // End of namespace Sci
diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp
index 0afdc3f2eb..eab1b90139 100644
--- a/engines/sci/engine/kernel32.cpp
+++ b/engines/sci/engine/kernel32.cpp
@@ -30,9 +30,8 @@
#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 "sci/graphics/screen.h"
#include "common/system.h"
@@ -337,7 +336,7 @@ static const char *sci21_default_knames[] = {
/*0x80*/ "Dummy",
/*0x81*/ "Dummy",
/*0x82*/ "Dummy",
- /*0x83*/ "Dummy",
+ /*0x83*/ "PrintDebug", // used by the Shivers 2 demo
/*0x84*/ "Dummy",
/*0x85*/ "Dummy",
/*0x86*/ "Dummy",
@@ -378,15 +377,17 @@ 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().
+void Kernel::setKernelNamesSci21(GameFeatures *features) {
+ // 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.
+ // 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) {
+ 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
@@ -400,7 +401,8 @@ void Kernel::setKernelNamesSci21() {
// 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.
+ // 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);
@@ -461,6 +463,13 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) {
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();
@@ -509,6 +518,19 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) {
return NULL_REG;
}
+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
@@ -594,21 +616,24 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) {
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));
+ 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(s->_segMan->sysStrings->_strings[sysStringId]._value + index1, string2 + index2, count);
+ 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].
+ // 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]);
}
@@ -791,8 +816,76 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv) {
nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsTop));
nsRect.right = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsRight));
nsRect.bottom = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsBottom));
+ 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)
- //warning("kOnMe: (%d, %d) on object %04x:%04x, parameter %d", argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), argv[3].toUint16());
+ 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;
+ }
+
+ /*
+ warning("kOnMe: (%d, %d) on object %04x:%04x (%s), rect (%d, %d, %d, %d), parameter %d",
+ argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), s->_segMan->getObjectName(argv[2]),
+ nsRect.left, nsRect.top, nsRect.right, nsRect.bottom,
+ argv[3].toUint16());
+ */
+
+ return make_reg(0, nsRect.contains(x, y));
+}
+
+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
+ 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
+ itemY = ((itemY * g_sci->_gfxScreen->getHeight()) / planeResY);
+ itemX = ((itemX * g_sci->_gfxScreen->getWidth()) / planeResX);
+ itemY += planeTop;
+ itemX += planeLeft;
+
+ nsRect.translate(itemX, itemY);
+ }
+
+ //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));
}
@@ -805,7 +898,7 @@ reg_t kInPolygon(EngineState *s, int argc, reg_t *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:
+ case 0: {
if (argc != 4) {
warning("kCreateTextBitmap(0): expected 4 arguments, got %i", argc);
return NULL_REG;
@@ -814,6 +907,22 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) {
Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text)));
debug("kCreateTextBitmap: %s", text.c_str());
}
+ default:
+ warning("CreateTextBitmap(%d)", argv[0].toUint16());
+ }
+
+ return NULL_REG;
+}
+
+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());
+ }
return NULL_REG;
}
diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp
index fd7711f196..7547ad5ab6 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;
@@ -67,7 +65,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 +77,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 +124,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 +149,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();
+ g_sci->_soundCmd->updateSci0Cues();
}
-#endif
return s->r_acc;
}
@@ -203,7 +201,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
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 3e0ecd1a28..807edc63a5 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;
@@ -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,27 +132,28 @@ 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());
+ warning(" -> 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());
+ warning(" -> 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
+ 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.
} else {
error("file_open: unsupported mode %d (filename '%s')", mode, englishName.c_str());
}
if (!inFile && !outFile) { // Failed
- debug(3, "file_open() failed");
+ debugC(2, kDebugLevelFile, " -> file_open() failed");
s->r_acc = SIGNAL_REG;
return;
}
@@ -163,7 +163,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);
}
@@ -173,14 +174,14 @@ void file_open(EngineState *s, const char *filename, int mode) {
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);
}
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);
+ debugC(2, kDebugLevelFile, "kFOpen(%s,0x%x)", name.c_str(), mode);
file_open(s, name.c_str(), mode);
return s->r_acc;
}
@@ -200,7 +201,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 +222,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 +243,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 +251,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 +266,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,
@@ -389,21 +332,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;
}
@@ -430,27 +377,108 @@ reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) {
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())
+ // 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;
@@ -463,9 +491,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 +511,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 +526,51 @@ 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());
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 +579,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 +599,37 @@ 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);
+ if ((savegameId < 1000) || (savegameId > 1999)) {
+ warning("Savegame ID %d is not allowed", savegameId);
+ return TRUE_REG;
+ }
+ savegameId -= 1000;
- savedir_nr = saves[savedir_nr].id;
- } else {
- // Loading from launcher, no change necessary
+ Common::Array<SavegameDesc> saves;
+ listSavegames(saves);
+ if (findSavegame(saves, savegameId) == -1) {
+ warning("Savegame ID %d not found", savegameId);
+ return TRUE_REG;
}
- 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::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+ Common::String filename = g_sci->getSavegameName(savegameId);
+ Common::SeekableReadStream *in;
+ if ((in = saveFileMan->openForLoading(filename))) {
+ // found a savegame file
- gamestate_restore(s, in);
- delete in;
+ gamestate_restore(s, in);
+ delete in;
- return s->r_acc;
- }
+ 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;
}
@@ -642,7 +680,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);
}
@@ -672,7 +711,8 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
case K_FILEIO_OPEN : {
Common::String name = s->_segMan->getString(argv[1]);
- // SCI32 can call K_FILEIO_OPEN with only two arguments. It seems to just be checking if it exists.
+ // 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();
// SQ4 floppy prepends /\ to the filenames
@@ -681,10 +721,10 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
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
+ // 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;
@@ -694,12 +734,12 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
warning("Attempted to open a file with an empty filename");
return SIGNAL_REG;
}
+ debugC(2, kDebugLevelFile, "kFileIO(open): %s, 0x%x", name.c_str(), mode);
file_open(s, name.c_str(), mode);
- debug(3, "K_FILEIO_OPEN(%s,0x%x)", name.c_str(), mode);
break;
}
case K_FILEIO_CLOSE : {
- debug(3, "K_FILEIO_CLOSE(%d)", argv[1].toUint16());
+ debugC(2, kDebugLevelFile, "kFileIO(close): %d", argv[1].toUint16());
FileHandle *f = getFileFromHandle(s, argv[1].toUint16());
if (f)
@@ -710,8 +750,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
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);
-
+ debugC(2, kDebugLevelFile, "kFileIO(readRaw): %d, %d", handle, size);
FileHandle *f = getFileFromHandle(s, handle);
if (f) {
@@ -727,7 +766,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
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);
+ debugC(2, kDebugLevelFile, "kFileIO(writeRaw): %d, %d", handle, size);
FileHandle *f = getFileFromHandle(s, handle);
if (f)
@@ -745,11 +784,13 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
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
+ // 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
+ // 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);
@@ -761,7 +802,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
saveFileMan->removeSavefile(wrappedName);
}
- debug(3, "K_FILEIO_UNLINK(%s)", name.c_str());
+ debugC(2, kDebugLevelFile, "kFileIO(unlink): %s", name.c_str());
// TODO/FIXME: Should we return something (like, a bool indicating
// whether deleting the save succeeded or failed)?
@@ -771,7 +812,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
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);
+ debugC(2, kDebugLevelFile, "kFileIO(readString): %d, %d", handle, size);
fgets_wrapper(s, buf, size, handle);
s->_segMan->memcpy(argv[1], (const byte*)buf, size);
@@ -782,7 +823,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
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);
+ debugC(2, kDebugLevelFile, "kFileIO(writeString): %d, %d", handle, size);
// CHECKME: Is the size parameter used at all?
// In the LSL5 password protection it is zero, and we should
@@ -798,7 +839,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
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);
+ debugC(2, kDebugLevelFile, "kFileIO(seek): %d, %d, %d", handle, offset, whence);
FileHandle *f = getFileFromHandle(s, handle);
if (f)
@@ -809,7 +850,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
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);
+ debugC(2, kDebugLevelFile, "kFileIO(findFirst): %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 == "*.*")
@@ -827,7 +868,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
break;
}
case K_FILEIO_FIND_NEXT : {
- debug(3, "K_FILEIO_FIND_NEXT()");
+ debugC(2, kDebugLevelFile, "kFileIO(findNext)");
s->r_acc = s->_dirseeker.nextFile(s->_segMan);
break;
}
@@ -849,14 +890,17 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
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
+ // 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
+ // 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++)
@@ -866,15 +910,15 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
exists = true;
}
- debug(3, "K_FILEIO_FILE_EXISTS(%s) -> %d", name.c_str(), exists);
+ debugC(2, kDebugLevelFile, "kFileIO(fileExists) %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]);
- // 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.
+ // 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
@@ -914,7 +958,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) {
break;
#endif
default:
- error("Unknown FileIO() sub-command: %d", func_nr);
+ error("kFileIO(): unknown sub-command: %d", func_nr);
}
return s->r_acc;
diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp
index abe55455de..29f7565ef9 100644
--- a/engines/sci/engine/kgraphics.cpp
+++ b/engines/sci/engine/kgraphics.cpp
@@ -37,8 +37,6 @@
#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"
@@ -48,7 +46,11 @@
#include "sci/graphics/paint16.h"
#include "sci/graphics/ports.h"
#include "sci/graphics/screen.h"
+#include "sci/graphics/text16.h"
#include "sci/graphics/view.h"
+#ifdef ENABLE_SCI32
+#include "sci/video/vmd_decoder.h"
+#endif
namespace Sci {
@@ -171,7 +173,7 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) {
g_sci->_gfxCursor->kernelSetView(argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), hotspot);
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 +186,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 +207,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 = (argc > 4) ? argv[4].toUint16() : 0;
+ 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 +332,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);
@@ -531,7 +521,7 @@ reg_t kBaseSetter(EngineState *s, int argc, reg_t *argv) {
// 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) {
+ if (s->currentRoomNumber() == 300 && g_sci->getGameId() == GID_LSL1) {
int top = readSelectorValue(s->_segMan, object, SELECTOR(brTop));
writeSelectorValue(s->_segMan, object, SELECTOR(brTop), top + 2);
}
@@ -545,64 +535,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 +609,82 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) {
}
if (paletteChanged)
g_sci->_gfxPalette->kernelAnimateSet();
- break;
}
- case 7: { // Save palette to heap
+ return s->r_acc;
+}
+
+reg_t kPaletteSave(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isVGA()) {
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 NULL_REG;
+}
+reg_t kPaletteRestore(EngineState *s, int argc, reg_t *argv) {
+ if (g_sci->getResMan()->isVGA()) {
+ warning("kPalette(8), restore palette from heap STUB");
+ }
return s->r_acc;
}
-// 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 +698,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,24 +715,24 @@ 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;
@@ -790,6 +790,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 +806,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 +823,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));
@@ -883,6 +885,18 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) {
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") {
+ // Remove "a:" from hero quest export default filename
+ text.deleteChar(0);
+ text.deleteChar(0);
+ s->_segMan->strcpy(textReference, text.c_str());
+ }
+ }
+ }
_k_GenericDrawControl(s, controlObject, false);
return NULL_REG;
@@ -989,24 +1003,6 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) {
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;
- }
-
g_sci->_gfxPaint16->kernelDrawCel(viewId, loopNo, celNo, x, y, priority, paletteNo, hiresMode, upscaledHiresHandle);
return s->r_acc;
@@ -1049,10 +1045,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;
@@ -1083,6 +1075,58 @@ 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);
}
+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.
@@ -1106,7 +1150,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
initGraphics(screenWidth, screenHeight, screenWidth > 320, NULL);
if (g_system->getScreenFormat().bytesPerPixel == 1) {
- warning("This video requires >8bpp color to be displayed, but could not switch to RGB color mode.");
+ error("This video requires >8bpp color to be displayed, but could not switch to RGB color mode.");
return NULL_REG;
}
@@ -1159,37 +1203,16 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) {
}
if (videoDecoder) {
- uint16 x = (screenWidth - videoDecoder->getWidth()) / 2;
- uint16 y = (screenHeight - videoDecoder->getHeight()) / 2;
-
- 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);
-
- if (videoDecoder->hasDirtyPalette())
- videoDecoder->setSystemPalette();
-
- g_system->updateScreen();
- }
- }
-
- Common::Event event;
- while (g_system->getEventManager()->pollEvent(event))
- ;
-
- g_system->delayMillis(10);
- }
+ 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
+ else {
g_sci->_gfxScreen->kernelSyncWithFramebuffer();
-
- delete videoDecoder;
+ g_sci->_gfxPalette->kernelSyncScreenPalette();
+ }
}
if (reshowCursor)
@@ -1213,6 +1236,9 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) {
warning("kRobot(init), id %d, obj %04x:%04x, flag %d, x=%d, y=%d", id, PRINT_REG(obj), flag, x, y);
}
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,30 +1254,140 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) {
return s->r_acc;
}
+
+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 (reshowCursor)
+ g_sci->_gfxCursor->kernelHide();
+
+ if (videoDecoder && videoDecoder->loadFile(fileName))
+ 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 = "PlayVMD - unsupported subop. 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());
+ break;
+ }
+
+ 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).
+ // 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
+// 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);
+ g_sci->_gfxText16->kernelTextFonts(argc, argv);
return s->r_acc;
}
reg_t kTextColors(EngineState *s, int argc, reg_t *argv) {
- g_sci->_gui->textColors(argc, argv);
+ g_sci->_gfxText16->kernelTextColors(argc, argv);
return s->r_acc;
}
diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp
index f06f3eec77..0701883a9b 100644
--- a/engines/sci/engine/klists.cpp
+++ b/engines/sci/engine/klists.cpp
@@ -37,12 +37,12 @@ static bool isSaneNodePointer(SegManager *segMan, reg_t addr) {
Node *node = segMan->lookupNode(addr);
if (!node) {
- warning("isSaneNodePointer: Node at %04x:%04x wasn't found", PRINT_REG(addr));
+ 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 +58,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);
+ Node *node_z = segMan->lookupNode(list->last);
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 +93,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 +101,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 +145,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 +159,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 +173,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 +250,30 @@ 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]);
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,19 +283,19 @@ 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]);
+ addToEnd(s, argv[0], argv[1]);
return s->r_acc;
}
@@ -352,23 +330,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 +380,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 +402,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 +417,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 +430,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 +499,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 +531,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 +565,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())
@@ -627,15 +608,15 @@ reg_t kList(EngineState *s, int argc, reg_t *argv) {
case 11:
return kAddToEnd(s, argc - 1, argv + 1);
case 12:
- warning("kList: unimplemented subfunction kAddBefore");
+ error("kList: unimplemented subfunction kAddBefore");
//return kAddBefore(s, argc - 1, argv + 1);
return NULL_REG;
case 13:
- warning("kList: unimplemented subfunction kMoveToFront");
+ error("kList: unimplemented subfunction kMoveToFront");
//return kMoveToFront(s, argc - 1, argv + 1);
return NULL_REG;
case 14:
- warning("kList: unimplemented subfunction kMoveToEnd");
+ error("kList: unimplemented subfunction kMoveToEnd");
//return kMoveToEnd(s, argc - 1, argv + 1);
return NULL_REG;
case 15:
@@ -655,7 +636,7 @@ reg_t kList(EngineState *s, int argc, reg_t *argv) {
case 22:
return kSort(s, argc - 1, argv + 1);
default:
- warning("kList: Unhandled case %d", argv[0].toUint16());
+ error("kList: Unhandled case %d", argv[0].toUint16());
return NULL_REG;
}
}
diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp
index dbf317860f..eab964d624 100644
--- a/engines/sci/engine/kmath.cpp
+++ b/engines/sci/engine/kmath.cpp
@@ -36,9 +36,6 @@ reg_t kRandom(EngineState *s, int argc, reg_t *argv) {
}
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 +109,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 +121,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 +133,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 +144,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..b8c62210f9 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,28 @@ 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->gameWasRestarted);
if (argc) { // Only happens during replay
if (!argv[0].toUint16()) // Set restarting flag
- s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED;
+ s->gameWasRestarted = false;
}
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)
+ // 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 (g_sci->getGameId() == GID_LSL3 && s->currentRoomNumber() == 290)
s->_throttleTrigger = true;
- if (!strcmp(g_sci->getGameID(), "iceman") && s->currentRoomNumber() == 27) {
+ else if (g_sci->getGameId() == GID_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;
- }
- s->_throttleTrigger = false;
- }
-
+ s->speedThrottler(neededSleep);
return s->r_acc;
}
@@ -106,7 +84,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 +102,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,8 +154,8 @@ 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;
}
@@ -190,12 +172,12 @@ 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 :
@@ -215,7 +197,7 @@ reg_t kGetTime(EngineState *s, int argc, reg_t *argv) {
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;
}
@@ -261,7 +243,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 +259,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 +317,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 +354,18 @@ 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;
+}
+
} // End of namespace Sci
diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp
index 499aeabcc6..ccef3d862a 100644
--- a/engines/sci/engine/kmovement.cpp
+++ b/engines/sci/engine/kmovement.cpp
@@ -33,42 +33,43 @@
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 +116,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
@@ -315,11 +316,11 @@ 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);
+ if (SELECTOR(cantBeHere) != -1) {
+ invokeSelector(s, client, SELECTOR(cantBeHere), argc, argv);
s->r_acc = make_reg(0, !s->r_acc.offset);
} else {
- invokeSelector(INV_SEL(s, client, canBeHere, kStopOnInvalidSelector), 0);
+ invokeSelector(s, client, SELECTOR(canBeHere), argc, argv);
}
if (!s->r_acc.offset) { // Contains the return value
@@ -335,7 +336,7 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) {
if ((getSciVersion() >= SCI_VERSION_1_EGA))
if (completed)
- invokeSelector(INV_SEL(s, mover, moveDone, kStopOnInvalidSelector), 0);
+ invokeSelector(s, mover, SELECTOR(moveDone), argc, argv);
return make_reg(0, completed);
}
@@ -373,14 +374,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 +390,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 +400,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));
@@ -439,11 +433,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 +451,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 +462,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..45493a95d2 100644
--- a/engines/sci/engine/kparse.cpp
+++ b/engines/sci/engine/kparse.cpp
@@ -94,8 +94,8 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) {
ResultWordList words;
reg_t event = argv[1];
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 */
@@ -118,7 +118,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 +141,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..fdaae3e121 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;
@@ -981,14 +1011,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 +1061,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 +1090,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 +1108,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 +1132,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 +1212,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);
@@ -1297,11 +1335,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 +1734,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 +1760,14 @@ 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 polygonData;
+ return output;
}
} // End of namespace Sci
diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp
index 722d0175d1..029943b070 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 = (ResourceType)(argv[0].toUint16() & 0x7f);
int resnr = argv[1].toUint16();
// Request to dynamically allocate hunk memory for later use
@@ -44,6 +48,29 @@ 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 = (ResourceType)(argv[0].toUint16() & 0x7f);
+ 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);
@@ -56,43 +83,46 @@ 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;
+ }
+
+ } 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
+ warning("[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);
+ 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) {
uint noun = argv[2].toUint16() & 0xff;
@@ -155,24 +185,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 +214,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 +239,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 +246,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..69ae68674b 100644
--- a/engines/sci/engine/ksound.cpp
+++ b/engines/sci/engine/ksound.cpp
@@ -39,12 +39,38 @@ 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(DoSoundDummy)
+CREATE_DOSOUND_FORWARD(DoSoundDispose)
+CREATE_DOSOUND_FORWARD(DoSoundMute)
+CREATE_DOSOUND_FORWARD(DoSoundStop)
+CREATE_DOSOUND_FORWARD(DoSoundStopAll)
+CREATE_DOSOUND_FORWARD(DoSoundPause)
+CREATE_DOSOUND_FORWARD(DoSoundResume)
+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(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 +98,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 +107,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 +137,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 +148,91 @@ 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:
+ warning("kDoAudio: Unhandled case 11, %d extra arguments passed", argc - 1);
+ break;
+ case 12:
+ // Seems to be audio sync, used in Pharkas. Silenced the warning due to
+ // the high level of spam it produces.
+ //warning("kDoAudio: Unhandled case 12, %d extra arguments passed", argc - 1);
+ break;
+ case 13:
+ // Used in Pharkas whenever a speech sample starts
+ 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 +269,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..f2f9543ad2 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]);
@@ -561,7 +567,7 @@ 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());
+ //debug("Setting quit string to '%s'", quitStr.c_str());
return s->r_acc;
}
@@ -578,7 +584,8 @@ 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());
diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp
index 07f8792471..18e60eb521 100644
--- a/engines/sci/engine/message.cpp
+++ b/engines/sci/engine/message.cpp
@@ -161,7 +161,7 @@ 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;
}
@@ -259,7 +259,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 +330,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;
}
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 9bf23dedf5..0fe5f2088a 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -33,24 +33,18 @@
#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/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 {
@@ -62,47 +56,11 @@ namespace Sci {
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) {
@@ -132,7 +90,7 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) {
fadeTickerStep = 0;
} else {
// A bit more optimized saving
- sync_reg_t(s, soundObj);
+ soundObj.saveLoadWithSerializer(s);
s.syncAsSint16LE(resourceId);
s.syncAsSint16LE(dataInc);
s.syncAsSint16LE(ticker);
@@ -156,7 +114,6 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) {
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
@@ -217,31 +174,18 @@ void syncArray(Common::Serializer &s, Common::Array<T> &arr) {
template <>
void syncWithSerializer(Common::Serializer &s, reg_t &obj) {
- sync_reg_t(s, obj);
+ obj.saveLoadWithSerializer(s);
}
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(12), 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 +201,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
-
- if (s.isLoading())
- obj->resetSegMan();
+ s.syncAsSint32LE(_clonesSegId);
+ s.syncAsSint32LE(_listsSegId);
+ s.syncAsSint32LE(_nodesSegId);
- 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);
+ obj.reg.saveLoadWithSerializer(s);
}
static void sync_SavegameMetadata(Common::Serializer &s, SavegameMetadata &obj) {
@@ -318,17 +243,20 @@ 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
+ s.syncString(tmp, VER(12), VER(23)); // OBSOLETE: Used to be game_version
// OBSOLETE: Saved menus. Skip all of the saved data
if (s.getVersion() < 14) {
@@ -347,7 +275,6 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
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
@@ -362,16 +289,14 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
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 (s.getVersion() >= 13 && 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 +304,14 @@ 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);
}
void LocalVariables::saveLoadWithSerializer(Common::Serializer &s) {
@@ -400,8 +322,8 @@ 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
+ _pos.saveLoadWithSerializer(s);
+ s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be variable_names_nr
s.syncAsSint32LE(_methodCount); // that's actually a uint16
syncArray<reg_t>(s, _variables);
@@ -418,18 +340,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);
+ obj.first.saveLoadWithSerializer(s);
+ obj.last.saveLoadWithSerializer(s);
}
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);
+ obj.pred.saveLoadWithSerializer(s);
+ obj.succ.saveLoadWithSerializer(s);
+ obj.key.saveLoadWithSerializer(s);
+ obj.value.saveLoadWithSerializer(s);
}
#ifdef ENABLE_SCI32
@@ -463,7 +385,7 @@ void syncWithSerializer(Common::Serializer &s, Table<SciArray<reg_t> >::Entry &o
if (s.isSaving())
value = obj.getValue(i);
- sync_reg_t(s, value);
+ value.saveLoadWithSerializer(s);
if (s.isLoading())
obj.setValue(i, value);
@@ -524,25 +446,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(12), VER(22)); // OBSOLETE: Used to be _bufSize
+ s.skip(4, VER(12), VER(22)); // OBSOLETE: Used to be _scriptSize
+ s.skip(4, VER(12), VER(22)); // OBSOLETE: Used to be _heapSize
+
+ s.skip(4, VER(12), VER(19)); // OBSOLETE: Used to be _numExports
+ s.skip(4, VER(12), VER(19)); // OBSOLETE: Used to be _numSynonyms
s.syncAsSint32LE(_lockers);
// Sync _objects. This is a hashmap, and we use the following on disk format:
@@ -570,7 +482,7 @@ void Script::saveLoadWithSerializer(Common::Serializer &s) {
}
}
- s.syncAsSint32LE(_localsOffset);
+ s.skip(4, VER(12), VER(20)); // OBSOLETE: Used to be _localsOffset
s.syncAsSint32LE(_localsSegment);
s.syncAsSint32LE(_markedAsDeleted);
@@ -622,30 +534,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 +582,35 @@ void SciMusic::saveLoadWithSerializer(Common::Serializer &s) {
}
}
}
-#endif
+
+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) {
+ 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));
+ }
+
+ processPlaySound((*i)->soundObj);
+ }
+ }
+}
#ifdef ENABLE_SCI32
void ArrayTable::saveLoadWithSerializer(Common::Serializer &ser) {
@@ -712,43 +628,13 @@ void StringTable::saveLoadWithSerializer(Common::Serializer &ser) {
}
#endif
-#pragma mark -
-
-
-int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename, const char *version) {
- TimeDate curTime;
- g_system->getTimeAndDate(curTime);
-
- SavegameMetadata meta;
- meta.savegame_version = CURRENT_SAVEGAME_VERSION;
- meta.savegame_name = savename;
- meta.game_version = version;
- meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF);
- meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF);
-
- if (s->execution_stack_base) {
- warning("Cannot save from below kernel function");
- return 1;
- }
-
- Common::Serializer ser(0, fh);
- sync_SavegameMetadata(ser, meta);
- Graphics::saveThumbnail(*fh);
- s->saveLoadWithSerializer(ser); // FIXME: Error handling?
-
- return 0;
+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: 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;
-}
-
-// 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 +647,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 +662,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 +672,70 @@ 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;
- if (getSciVersion() > SCI_VERSION_01)
- it_type = SCI_SONG_ITERATOR_TYPE_SCI1;
- else
- it_type = SCI_SONG_ITERATOR_TYPE_SCI0;
+ 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
+}
- seeker = s->_sound._songlib._lib;
- while (seeker) {
- SongIterator *base, *ff = 0;
- int oldstatus;
- SongIterator::Message msg;
+#pragma mark -
- base = ff = build_iterator(g_sci->getResMan(), seeker->_resourceNum, it_type, seeker->_handle);
- if (seeker->_restoreBehavior == RESTORE_BEHAVIOR_CONTINUE)
- ff = new_fast_forward_iterator(base, seeker->_restoreTime);
- ff->init();
- msg = SongIterator::Message(seeker->_handle, SIMSG_SET_LOOPS(seeker->_loops));
- songit_handle_message(&ff, msg);
- msg = SongIterator::Message(seeker->_handle, SIMSG_SET_HOLD(seeker->_hold));
- songit_handle_message(&ff, msg);
+bool gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename, const char *version) {
+ TimeDate curTime;
+ g_system->getTimeAndDate(curTime);
- oldstatus = seeker->_status;
- seeker->_status = SOUND_STATUS_STOPPED;
- seeker->_it = ff;
- s->_sound.sfx_song_set_status(seeker->_handle, oldstatus);
- seeker = seeker->_next;
+ SavegameMetadata meta;
+ meta.savegame_version = CURRENT_SAVEGAME_VERSION;
+ meta.savegame_name = savename;
+ meta.game_version = version;
+ meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF);
+ meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF);
+
+ Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false);
+ meta.script0_size = script0->size;
+ meta.game_object_offset = g_sci->getGameObject().offset;
+
+ 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,85 +748,62 @@ 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::Surface *thumbnail = new Graphics::Surface();
+ assert(thumbnail);
+ Graphics::loadThumbnail(*fh, *thumbnail);
+ delete thumbnail;
+ thumbnail = 0;
+
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();
+
+ g_sci->_soundCmd->reconstructPlayList(meta.savegame_version);
// Message state:
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->restoring = true;
- s->script_abort_flag = 2; // Abort current game with replay
+ s->abortScriptProcessing = kAbortLoadGame;
s->shrinkStackToBase();
}
diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h
index 7be05381da..9a882f2bf7 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 = 23,
+ MINIMUM_SAVEGAME_VERSION = 12
};
// 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..a293f81d2f 100644
--- a/engines/sci/engine/script.cpp
+++ b/engines/sci/engine/script.cpp
@@ -35,431 +35,553 @@
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);
+ }
+}
+
+bool Script::isValidOffset(uint16 offset) const {
+ return offset < _bufSize;
+}
+
+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();
+ }
- curOffset += objLength - 4;
- } while (objType != 0 && curOffset < scr->getScriptSize() - 2);
+ SegmentRef ret;
+ ret.isRaw = true;
+ ret.maxSize = _bufSize - pointer.offset;
+ ret.raw = _buf + pointer.offset;
+ return ret;
}
-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;
+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) {
+ // WORKAROUND for an invalid species access in the demo of LSL2
+ if (g_sci->getGameId() == GID_LSL2 && g_sci->isDemo() && species == (int)segMan->classTableSize())
+ segMan->resizeClassTable(segMan->classTableSize() + 1);
- reg.offset -= SCRIPT_OBJECT_MAGIC_OFFSET;
+ if (species < 0 || species >= (int)segMan->classTableSize())
+ error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d\n",
+ species, species, segMan->classTableSize(), _nr);
- superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass...
+ SegmentId segmentId = segMan->getScriptSegment(_nr);
+ segMan->setClassOffset(species, make_reg(segmentId, classpos));
+ }
+
+ seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * mult;
+ }
+}
- if (superclass >= 0) {
- int superclass_script = segMan->getClass(superclass).script;
+void Script::initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId) {
+ bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
+ const byte *seeker = _buf + (oldScriptHeader ? 2 : 0);
+
+ 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 && g_sci->getSciLanguage() == K_LANG_FRENCH) {
+ // Script 202 of KQ5 French has an invalid object. This is non-fatal.
+ } 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 b465ab3d4e..915a6fa994 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());
}
}
@@ -205,12 +201,12 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
if (pos == s->xs->addr.pc) { // Extra information if debugging the current opcode
if (opcode == op_callk) {
- int stackframe = (scr[pos.offset + 2] >> 1) + (s->restAdjustCur);
+ int stackframe = (scr[pos.offset + 2] >> 1) + (s->restAdjust);
int argc = ((s->xs->sp)[- stackframe - 1]).offset;
bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY);
if (!oldScriptHeader)
- argc += (s->restAdjustCur);
+ argc += (s->restAdjust);
printf(" Kernel params: (");
@@ -221,7 +217,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod
}
printf(")\n");
} else if ((opcode == op_send) || (opcode == op_self)) {
- int restmod = s->restAdjustCur;
+ int restmod = s->restAdjust;
int stackframe = (scr[pos.offset + 1] >> 1) + restmod;
reg_t *sb = s->xs->sp;
uint16 selector;
@@ -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,19 +473,17 @@ 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);
@@ -551,46 +531,40 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) {
}
}
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..ef2279e492 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,36 +472,36 @@ 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;
}
@@ -567,18 +512,17 @@ Node *SegManager::lookupNode(reg_t addr) {
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));
+ error("Attempt to use invalid or discarded reference %04x:%04x as list node", PRINT_REG(addr));
return NULL;
}
@@ -606,7 +550,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 +590,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 +643,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 +778,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 +800,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 +829,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);
@@ -901,14 +862,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 +902,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 +940,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..a7f5f8517f 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
@@ -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..2465576302 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,25 +116,31 @@ 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>();
+ }
};
@@ -195,7 +201,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 +337,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 +355,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 +443,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 +458,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 +469,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 +480,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 +493,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 +519,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 +629,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 +653,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..00480743cc 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"
@@ -157,6 +158,9 @@ void Kernel::mapSelectors() {
FIND_SELECTOR(scaleSignal);
FIND_SELECTOR(scaleX);
FIND_SELECTOR(scaleY);
+ FIND_SELECTOR(maxScale);
+ FIND_SELECTOR(vanishingX);
+ FIND_SELECTOR(vanishingY);
FIND_SELECTOR(iconIndex);
#ifdef ENABLE_SCI32
@@ -188,42 +192,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++)
@@ -238,24 +237,6 @@ int invokeSelectorArgv(EngineState *s, reg_t object, int selectorId, SelectorInv
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;
}
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..acb7912d8d 100644
--- a/engines/sci/engine/selector.h
+++ b/engines/sci/engine/selector.h
@@ -30,13 +30,118 @@
#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 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
+
+#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
};
/**
@@ -71,18 +176,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..36b03c0ad9 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;
+
+ if (duration < neededSleep) {
+ g_sci->sleep(neededSleep - duration);
+ _throttleLastTime = g_system->getMillis();
+ } else {
+ _throttleLastTime = curTime;
+ }
+ _throttleTrigger = false;
+ }
+}
- time = g_system->getMillis();
- r_acc = make_reg(0, ((long)time - (long)last_wait_time) * 60 / 1000);
- last_wait_time = time;
+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;
diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h
index bcdf66d6ef..243a460645 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,15 @@ 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
};
class FileHandle {
@@ -105,19 +113,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 +130,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,12 +141,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 restAdjustCur; /**< current &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 */
@@ -152,35 +154,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
+ 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
- Script *script_000; /**< script 000, e.g. for globals */
+ AbortGameState abortScriptProcessing;
+ bool gameWasRestarted;
- int loadFromLauncher;
-
- /**
- * 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;
@@ -197,8 +195,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..85089e74c8 100644
--- a/engines/sci/engine/static_selectors.cpp
+++ b/engines/sci/engine/static_selectors.cpp
@@ -100,13 +100,24 @@ static const SelectorRemap sciSelectorRemap[] = {
{ 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,26 @@ 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";
+ }
+
#ifdef ENABLE_SCI32
} else {
// SCI2+
diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp
index 1dcdf450ba..8108440102 100644
--- a/engines/sci/engine/vm.cpp
+++ b/engines/sci/engine/vm.cpp
@@ -30,24 +30,104 @@
#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"
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)
+#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() {
+ 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
+}
+
/**
* Adds an entry to the top of the execution stack.
*
@@ -59,6 +139,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 +151,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 +176,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 +213,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 +224,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 +242,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 && getSciVersion() <= SCI_VERSION_1_1 && 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 +262,139 @@ 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))
+struct SciTrackOriginReply {
+ int scriptNr;
+ Common::String objectName;
+ Common::String methodName;
+ int localCallOffset;
+};
+
+static reg_t 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();
+
+ 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->objectName) {
+ if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr
+ && ((workaround->inheritanceLevel == -1) || (workaround->inheritanceLevel == inheritanceLevel))
+ && (workaround->objectName == searchObjectName)
+ && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->debugLocalCallOffset && 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;
+ return make_reg(0xFFFF, 0xFFFF);
+}
+
+// gameID, scriptNr,lvl, object-name, method-name, call, index, replace
+static const SciWorkaroundEntry uninitializedReadWorkarounds[] = {
+ { GID_LAURABOW2, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu
+ { GID_FREDDYPHARKAS, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu
+ { GID_FREDDYPHARKAS, 31, 0, "quitWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu
+ { GID_GK2, 11, 0, "", "export 10", -1, 3, { 0, 0 } }, // called when the game starts
+ { GID_JONES, 232, 0, "weekendText", "draw", 0x3d3, 0, { 0, 0 } }, // jones/cd only - gets called during the game
+ { GID_JONES, 255, 0, "", "export 0", -1, 13, { 0, 0 } }, // jones/ega&vga only - called when the game starts
+ { GID_JONES, 255, 0, "", "export 0", -1, 14, { 0, 0 } }, // jones/ega&vga only - called when the game starts
+ { GID_LSL1, 720, 0, "rm720", "init", -1, 0, { 0, 0 } }, // age check room
+ { GID_LSL3, 997, 0, "TheMenuBar", "handleEvent", -1, 1, { 0, 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, 928, -1, "Narrator", "startText", -1, 0, { 0, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class
+ { GID_ISLANDBRAIN, 140, 0, "piece", "init", -1, 3, { 0, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0
+ { GID_ISLANDBRAIN, 268, 0, "anElement", "select", -1, 0, { 0, 0 } }, // elements puzzle, gets used before super TextIcon
+ { GID_KQ5, 0, 0, "", "export 29", -1, 3, { 0, 0 } }, // called when playing harp for the harpies, is used for kDoAudio
+ { GID_KQ5, 25, 0, "rm025", "doit", -1, 0, { 0, 0 } }, // inside witch forest, where the walking rock is
+ { GID_KQ6, 903, 0, "controlWin", "open", -1, 4, { 0, 0 } }, // when opening the controls window (save, load etc)
+ { GID_KQ6, 500, 0, "rm500", "init", -1, 0, { 0, 0 } }, // going to island of the beast
+ { GID_KQ6, 520, 0, "rm520", "init", -1, 0, { 0, 0 } }, // going to boiling water trap on beast isle
+ { GID_KQ6, 30, 0, "rats", "changeState", -1, 0, { 0, 0 } }, // rats in the catacombs
+ { GID_LSL6, 85, 0, "washcloth", "doVerb", -1, 0, { 0, 0 } }, // washcloth in inventory
+ { GID_SQ1, 703, 0, "", "export 1", -1, 0, { 0, 0 } }, // sub that's called from several objects while on sarien battle cruiser
+ { GID_SQ1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { 0, 0 } }, // export 1, but called locally (when shooting at aliens)
+ { GID_SQ4, 928, 0, "Narrator", "startText", -1, 1000, { 0, 1 } }, // sq4cd: method returns this to the caller
+ { GID_SQ6, 0, 0, "SQ6", "init", -1, 2, { 0, 0 } }, // called when the game starts
+ { GID_SQ6, 64950, 0, "View", "handleEvent", -1, 0, { 0, 0 } }, // called when pressing "Start game" in the main menu
+ SCI_WORKAROUNDENTRY_TERMINATOR
+};
+
+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;
+ r[index] = trackOriginAndFindWorkaround(index, uninitializedReadWorkarounds, &originReply);
+ if ((r[index].segment == 0xFFFF) && (r[index].offset == 0xFFFF))
+ error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %x)", index, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset);
+ 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
+ warning("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,44 +413,34 @@ 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:
@@ -247,12 +450,32 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i
#define PUSH32(a) (*(validate_stack_addr(s, (s->xs->sp)++)) = (a))
#define POP32() (*(validate_stack_addr(s, --(s->xs->sp))))
+bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) {
+ if (_debugState._activeBreakpointTypes & BREAK_EXPORT) {
+ uint32 bpaddress;
+
+ bpaddress = (script << 16 | pubfunct);
+
+ Common::List<Breakpoint>::const_iterator bp;
+ for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) {
+ if (bp->type == BREAK_EXPORT && bp->address == bpaddress) {
+ _console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct);
+ _debugState.debugging = true;
+ _debugState.breakpointWasHit = true;
+ return true;;
+ }
+ }
+ }
+
+ return false;
+}
+
ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp) {
int seg = s->_segMan->getScriptSegment(script);
Script *scr = s->_segMan->getScriptIfLoaded(seg);
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 +493,9 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP
}
// Check if a breakpoint is set on this method
- if (g_debugState._activeBreakpointTypes & BREAK_EXPORT) {
- uint32 bpaddress;
-
- bpaddress = (script << 16 | pubfunct);
-
- Common::List<Breakpoint>::const_iterator bp;
- for (bp = g_debugState._breakpoints.begin(); bp != g_debugState._breakpoints.end(); ++bp) {
- if (bp->type == BREAK_EXPORT && bp->address == bpaddress) {
- Console *con = g_sci->getSciDebugger();
- con->DebugPrintf("Break on script %d, export %d\n", script, pubfunct);
- g_debugState.debugging = true;
- g_debugState.breakpointWasHit = true;
- break;
- }
- }
- }
+ g_sci->checkExportBreakpoint(script, pubfunct);
- return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, calling_obj, s->_executionStack.size()-1, seg);
+ return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, -1, calling_obj, s->_executionStack.size()-1, seg);
}
@@ -297,7 +505,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 +533,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 +581,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 +617,30 @@ 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)
- 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));
+ // argc can indeed be bigger than 1 in some cases, and it's usually the
+ // result of a script bug
+
+ const char *objectName = s->_segMan->getObjectName(send_obj);
+
+ if (!strcmp(objectName, "Sq4GlobalNarrator") && selector == 606) {
+ // SQ4 has a script bug in the Sq4GlobalNarrator object when invoking the
+ // returnVal selector, which doesn't affect gameplay, thus don't diplay it
+ } else if (!strcmp(objectName, "longSong") && selector == 3 && g_sci->getGameId() == GID_QFG1) {
+ // QFG1VGA has a script bug in the longSong object when invoking the
+ // loop selector, which doesn't affect gameplay, thus don't diplay it
+ } else if (!strcmp(objectName, "PuzPiece") && selector == 77 && g_sci->getGameId() == GID_CASTLEBRAIN) {
+ // Castle of Dr. Brain has a script bug in the PuzPiece object when invoking
+ // the value selector, which doesn't affect gameplay, thus don't display it
+ } else {
+ // Unknown script bug, show it. Usually these aren't fatal.
+ reg_t oldReg = *varp.getPointer(s->_segMan);
+ reg_t newReg = argp[1];
+ const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str();
+ warning("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 +667,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 +721,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 +730,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 +740,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 +764,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 +775,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 +802,114 @@ static reg_t pointer_add(EngineState *s, reg_t base, int offset) {
}
}
-static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) {
-
- if (kernelFuncNum >= (int)g_sci->getKernel()->_kernelFuncs.size())
- error("Invalid kernel function 0x%x requested", kernelFuncNum);
+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;
+}
- 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;
+ reg_t workaround;
+ workaround = trackOriginAndFindWorkaround(0, kernelCall.workarounds, &originReply);
+ if ((workaround.segment == 0xFFFF) && (workaround.offset == 0xFFFF)) {
+ kernel->signatureDebug(kernelCall.signature, argc, argv);
+ error("[VM] k%s[%x]: signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, kernelCallNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset);
}
+ // FIXME: implement some real workaround type logic - ignore call, still do call etc.
+ if (workaround.segment == 2)
+ s->r_acc = make_reg(0, workaround.offset);
+ if (workaround.segment)
+ return;
+ }
- // 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);
} else {
- Common::String warningMsg = "Dummy function " + kernelFunc.orig_name +
- Common::String::printf("[0x%x]", kernelFuncNum) +
- " invoked - ignoring. Params: " +
- Common::String::printf("%d", argc) + " (";
+ // 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;
+ reg_t workaround;
+ workaround = trackOriginAndFindWorkaround(0, kernelSubCall.workarounds, &originReply);
+ if ((workaround.segment == 0xFFFF) && (workaround.offset == 0xFFFF)) {
+ 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, localCall %x)", kernelCall.name, subCallName, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset);
+ }
+ error("[VM] k%s: signature mismatch via method %s::%s (script %d, localCall %x)", kernelSubCall.name, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset);
+ }
+ // FIXME: implement some real workaround type logic - ignore call, still do call etc.
+ if (workaround.segment == 2)
+ s->r_acc = make_reg(0, workaround.offset);
+ if (workaround.segment)
+ return;
+ }
+ 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 0
+ // Used for debugging
+ Common::String debugMsg = Common::String::printf("%s [0x%x]", kernelCall.name, kernelCallNr) +
+ Common::String::printf(", %d params: ", argc) +
+ " (";
for (int i = 0; i < argc; i++) {
- warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i]));
- warningMsg += (i == argc - 1 ? ")" : ", ");
+ debugMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i]));
+ debugMsg += (i == argc - 1 ? ")" : ", ");
}
- warning("%s", warningMsg.c_str());
- }
+ debugMsg += ", result: " + Common::String::printf("%04x:%04x", PRINT_REG(s->r_acc));
+ debug("%s", debugMsg.c_str());
+#endif
+
+ // 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)
@@ -709,50 +981,29 @@ int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4])
void run_vm(EngineState *s, bool restoring) {
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->restAdjustCur = 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;
-
-#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;
+ s->executionStackBase = s->_executionStack.size() - 1;
- // 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 +1011,90 @@ 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) {
+ // FIXME: Why does this happen? Is the script not loaded yet at this point?
+ warning("Could not find local script from segment %x", s->xs->local_segment);
+ local_script = NULL;
+ s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL;
+ s->variablesMax[VAR_LOCAL] = 0;
} 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();
}
-#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)
+ // Binary not
s->r_acc = ACC_ARITHMETIC_L(0xffff ^ /*acc*/);
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;
@@ -912,23 +1152,23 @@ void run_vm(EngineState *s, bool restoring) {
s->r_acc = ACC_ARITHMETIC_L(((int16)POP()) * (int16)/*acc*/);
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)
+ int16 divisor = signed_validate_arithmetic(s->r_acc);
+ s->r_acc = make_reg(0, (divisor != 0 ? ((int16)POP()) / divisor : 0));
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)
+ int16 modulo = signed_validate_arithmetic(s->r_acc);
+ s->r_acc = make_reg(0, (modulo != 0 ? ((int16)POP()) % modulo : 0));
break;
-
+ }
case op_shr: // 0x06 (06)
+ // Shift right logical
s->r_acc = ACC_ARITHMETIC_L(((uint16)POP()) >> /*acc*/);
break;
case op_shl: // 0x07 (07)
+ // Shift left logical
s->r_acc = ACC_ARITHMETIC_L(((uint16)POP()) << /*acc*/);
break;
@@ -954,6 +1194,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 +1202,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 +1210,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,11 +1218,18 @@ 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 if (r_temp.segment && !s->r_acc.segment) {
+ if (s->r_acc.offset >= 1000)
+ error("[VM] op_gt: comparsion between a pointer and number");
+ // Pseudo-WORKAROUND: sierra allows any pointer <-> value comparsion
+ // Happens in SQ1, room 28, when throwing the water at Orat
+ s->r_acc = make_reg(0, 1);
} else
s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) > (int16)/*acc*/);
break;
case op_ge_: // 0x10 (16)
+ // >=
s->r_prev = s->r_acc;
r_temp = POP32();
if (r_temp.segment && s->r_acc.segment) {
@@ -991,17 +1241,25 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_lt_: // 0x11 (17)
+ // <
s->r_prev = s->r_acc;
r_temp = POP32();
if (r_temp.segment && s->r_acc.segment) {
if (r_temp.segment != s->r_acc.segment)
warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc));
s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset < s->r_acc.offset);
+ } else if (r_temp.segment && !s->r_acc.segment) {
+ if (s->r_acc.offset >= 1000)
+ error("[VM] op_lt: comparsion between a pointer and number");
+ // Pseudo-WORKAROUND: sierra allows any pointer <-> value comparsion
+ // Happens in SQ1, room 58, when giving id-card to robot
+ s->r_acc = make_reg(0, 1);
} else
s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) < (int16)/*acc*/);
break;
case op_le_: // 0x12 (18)
+ // <=
s->r_prev = s->r_acc;
r_temp = POP32();
if (r_temp.segment && s->r_acc.segment) {
@@ -1013,6 +1271,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_ugt_: // 0x13 (19)
+ // > (unsigned)
s->r_prev = s->r_acc;
r_temp = POP32();
@@ -1024,8 +1283,8 @@ 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)
@@ -1035,6 +1294,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_uge_: // 0x14 (20)
+ // >= (unsigned)
s->r_prev = s->r_acc;
r_temp = POP32();
@@ -1048,6 +1308,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_ult_: // 0x15 (21)
+ // < (unsigned)
s->r_prev = s->r_acc;
r_temp = POP32();
@@ -1061,6 +1322,7 @@ void run_vm(EngineState *s, bool restoring) {
break;
case op_ule_: // 0x16 (22)
+ // <= (unsigned)
s->r_prev = s->r_acc;
r_temp = POP32();
@@ -1074,11 +1336,13 @@ void run_vm(EngineState *s, bool restoring) {
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,45 +1352,56 @@ 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->restAdjustCur;
+ + 1 + s->restAdjust;
StackPtr call_base = s->xs->sp - argc;
- s->xs->sp[1].offset += s->restAdjustCur;
+ 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->restAdjustCur,
- call_base, NULL_SELECTOR, s->xs->objp,
+ (validate_arithmetic(*call_base)) + s->restAdjust,
+ call_base, NULL_SELECTOR, -1, localCallOffset, s->xs->objp,
s->_executionStack.size()-1, s->xs->local_segment);
- s->restAdjustCur = 0; // Used up the &rest adjustment
+ s->restAdjust = 0; // Used up the &rest adjustment
s->xs->sp = call_base;
s->_executionStackPosChanged = true;
@@ -1134,74 +1409,80 @@ 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) {
- s->xs->sp -= s->restAdjustCur;
- s->restAdjust = 0; // We just used up the s->restAdjustCur, remember?
- }
+ if (!oldScriptHeader)
+ s->xs->sp -= s->restAdjust;
int argc = validate_arithmetic(s->xs->sp[0]);
if (!oldScriptHeader)
- argc += s->restAdjustCur;
+ argc += s->restAdjust;
callKernelFunc(s, opparams[0], argc);
if (!oldScriptHeader)
- s->restAdjustCur = s->restAdjust;
+ s->restAdjust = 0;
// Calculate xs again: The kernel function might
// have spawned a new VM
xs_new = &(s->_executionStack.back());
s->_executionStackPosChanged = true;
+
+ // If a game is being loaded, stop processing
+ if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit())
+ return; // Stop processing
+
break;
}
case op_callb: // 0x22 (34)
- temp = ((opparams[1] >> 1) + s->restAdjustCur + 1);
+ // Call base script
+ temp = ((opparams[1] >> 1) + s->restAdjust + 1);
s_temp = s->xs->sp;
s->xs->sp -= temp;
- s->xs->sp[0].offset += s->restAdjustCur;
+ s->xs->sp[0].offset += s->restAdjust;
xs_new = execute_method(s, 0, opparams[0], s_temp, s->xs->objp,
s->xs->sp[0].offset, s->xs->sp);
- s->restAdjustCur = 0; // Used up the &rest adjustment
+ s->restAdjust = 0; // Used up the &rest adjustment
if (xs_new) // in case of error, keep old stack
s->_executionStackPosChanged = true;
break;
case op_calle: // 0x23 (35)
- temp = ((opparams[2] >> 1) + s->restAdjustCur + 1);
+ // Call external script
+ temp = ((opparams[2] >> 1) + s->restAdjust + 1);
s_temp = s->xs->sp;
s->xs->sp -= temp;
- s->xs->sp[0].offset += s->restAdjustCur;
+ s->xs->sp[0].offset += s->restAdjust;
xs_new = execute_method(s, opparams[0], opparams[1], s_temp, s->xs->objp,
s->xs->sp[0].offset, s->xs->sp);
- s->restAdjustCur = 0; // Used up the &rest adjustment
+ s->restAdjust = 0; // Used up the &rest adjustment
if (xs_new) // in case of error, keep old stack
s->_executionStackPosChanged = true;
break;
case op_ret: // 0x24 (36)
+ // Return from an execution loop started by call, calle, callb, send, self or super
do {
StackPtr old_sp2 = 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->restAdjustCur; // Update &rest
return; // "Hard" return
}
@@ -1233,17 +1514,18 @@ 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->restAdjustCur); // Adjust stack
+ s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack
- s->xs->sp[1].offset += s->restAdjustCur;
+ s->xs->sp[1].offset += s->restAdjust;
xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp,
- (int)(opparams[0] >> 1) + (uint16)s->restAdjustCur, s->xs->sp);
+ (int)(opparams[0] >> 1) + (uint16)s->restAdjust, s->xs->sp);
if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- s->restAdjustCur = 0;
+ s->restAdjust = 0;
break;
@@ -1253,6 +1535,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,45 +1545,48 @@ 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->restAdjustCur); // Adjust stack
+ s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack
- s->xs->sp[1].offset += s->restAdjustCur;
+ s->xs->sp[1].offset += s->restAdjust;
xs_new = send_selector(s, s->xs->objp, s->xs->objp,
- s_temp, (int)(opparams[0] >> 1) + (uint16)s->restAdjustCur,
+ s_temp, (int)(opparams[0] >> 1) + (uint16)s->restAdjust,
s->xs->sp);
if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- s->restAdjustCur = 0;
+ s->restAdjust = 0;
break;
case op_super: // 0x2b (43)
+ // Send to any class
r_temp = s->_segMan->getClassAddress(opparams[0], SCRIPT_GET_LOAD, s->xs->addr.pc);
if (!r_temp.segment)
error("[VM]: Invalid superclass in object");
else {
s_temp = s->xs->sp;
- s->xs->sp -= ((opparams[1] >> 1) + s->restAdjustCur); // Adjust stack
+ s->xs->sp -= ((opparams[1] >> 1) + s->restAdjust); // Adjust stack
- s->xs->sp[1].offset += s->restAdjustCur;
+ s->xs->sp[1].offset += s->restAdjust;
xs_new = send_selector(s, r_temp, s->xs->objp, s_temp,
- (int)(opparams[1] >> 1) + (uint16)s->restAdjustCur,
+ (int)(opparams[1] >> 1) + (uint16)s->restAdjust,
s->xs->sp);
if (xs_new && xs_new != s->xs)
s->_executionStackPosChanged = true;
- s->restAdjustCur = 0;
+ s->restAdjust = 0;
}
break;
case op_rest: // 0x2c (44)
+ // Pushes all or part of the parameter variable list on the stack
temp = (uint16) opparams[0]; // First argument
- s->restAdjustCur = MAX<int16>(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't
+ s->restAdjust = MAX<int16>(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't
for (; temp <= s->xs->argc; temp++)
PUSH32(s->xs->variables_argp[temp]);
@@ -1308,12 +1594,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 +1613,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 +1622,60 @@ 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*/);
+ // Incement Property and copy To Accumulator
+ s->r_acc = validate_property(obj, (opparams[0] >> 1));
+ s->r_acc = validate_property(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(1 + /*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
+ s->r_acc = validate_property(obj, (opparams[0] >> 1));
+ s->r_acc = validate_property(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(-1 + /*acc*/);
break;
}
case op_ipTos: // 0x37 (55)
- validate_arithmetic(OBJ_PROPERTY(obj, (opparams[0] >> 1)));
- temp = ++OBJ_PROPERTY(obj, (opparams[0] >> 1)).offset;
+ // Increment Property and push to Stack
+ validate_arithmetic(validate_property(obj, (opparams[0] >> 1)));
+ temp = ++validate_property(obj, (opparams[0] >> 1)).offset;
PUSH(temp);
break;
case op_dpTos: // 0x38 (56)
- validate_arithmetic(OBJ_PROPERTY(obj, (opparams[0] >> 1)));
- temp = --OBJ_PROPERTY(obj, (opparams[0] >> 1)).offset;
+ // Decrement Property and push to Stack
+ validate_arithmetic(validate_property(obj, (opparams[0] >> 1)));
+ temp = --validate_property(obj, (opparams[0] >> 1)).offset;
PUSH(temp);
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 +1689,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 +1710,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 +1734,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 +1747,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 +1799,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 +1809,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 +1825,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 +1836,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 +1853,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 +1871,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 +1888,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 +1906,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 +1923,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 +1941,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 +1958,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,100 +1980,15 @@ 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;
+ ++s->scriptStepCounter;
}
}
-static void _init_stack_base_with_selector(EngineState *s, Selector selector) {
- s->stack_base[0] = make_reg(0, (uint16)selector);
- s->stack_base[1] = NULL_REG;
-}
-
-static EngineState *_game_run(EngineState *&s) {
- 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;
- }
- // 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 {
Object *o = segMan->getObject(obj);
return o ? &o->getVariableRef(varindex) : 0;
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index 67a6bd0dc3..81ec4f1c61 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.
@@ -283,14 +326,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 +349,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..828fba3d7d 100644
--- a/engines/sci/engine/vm_types.h
+++ b/engines/sci/engine/vm_types.h
@@ -27,6 +27,7 @@
#define SCI_ENGINE_VM_TYPES_H
#include "common/scummsys.h"
+#include "common/serializer.h"
namespace Sci {
@@ -56,6 +57,11 @@ struct reg_t {
int16 toSint16() const {
return (int16) offset;
}
+
+ void saveLoadWithSerializer(Common::Serializer &s) {
+ s.syncAsUint16LE(segment);
+ s.syncAsUint16LE(offset);
+ }
};
static inline reg_t make_reg(SegmentId segment, uint16 offset) {
@@ -81,6 +87,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/event.cpp b/engines/sci/event.cpp
index c3be22b143..a100dda27c 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;
@@ -315,22 +335,26 @@ sciEvent SciEvent::getFromScummVM() {
return input;
}
-sciEvent SciEvent::get(unsigned int mask) {
+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();
+ // 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();
+ }
// 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 +404,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..30098b0f6e 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,22 @@ 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);
+ 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..6fb427500d 100644
--- a/engines/sci/graphics/animate.cpp
+++ b/engines/sci/graphics/animate.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"
@@ -35,6 +36,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 +50,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 +83,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,7 +92,12 @@ 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);
+ 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
curNode = _s->_segMan->lookupNode(curAddress);
}
@@ -108,99 +110,64 @@ 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);
}
@@ -211,47 +178,73 @@ void GfxAnimate::makeSortedList(List *list) {
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;
// 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);
+ }
}
// 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);
} 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);
}
- 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);
+ 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);
- signal = listEntry->signal;
+ signal = it->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 +253,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 +408,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 +436,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 +465,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,33 +491,28 @@ 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++;
}
}
@@ -567,7 +521,7 @@ void GfxAnimate::addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celN
Common::Rect celRect;
// Create rect according to coordinates and given cel
- view->getCelRect(loopNo, celNo, leftPos, topPos, priority, &celRect);
+ view->getCelRect(loopNo, celNo, leftPos, topPos, priority, celRect);
_paint16->drawCel(view, loopNo, celNo, celRect, priority, 0);
}
@@ -592,6 +546,9 @@ void GfxAnimate::animateShowPic() {
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 +563,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 +575,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,7 +593,7 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t
updateScreen(old_picNotValid);
restoreAndDelete(argc, argv);
- if (getLastCastCount() > 1)
+ if (_lastCastData.size() > 1)
_s->_throttleTrigger = true;
_ports->setPort(oldPort);
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..8caa28b3a1 100644
--- a/engines/sci/graphics/cache.cpp
+++ b/engines/sci/graphics/cache.cpp
@@ -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..31c2b210ce 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"
@@ -126,14 +127,22 @@ 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) {
+ if (view->isSci2Hires())
+ _screen->adjustToUpscaledCoordinates(y, x);
+
+ view->getCelRect(loopNo, celNo, x, y, z, celRect);
+
+ if (view->isSci2Hires()) {
+ _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left);
+ _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right);
+ }
+
+ 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);
@@ -174,19 +183,19 @@ bool GfxCompare::kernelCanBeHere(reg_t curObject, reg_t listReference) {
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));
@@ -199,7 +208,16 @@ void GfxCompare::kernelBaseSetter(reg_t object) {
GfxView *tmpView = _cache->getView(viewId);
Common::Rect celRect;
- tmpView->getCelRect(loopNo, celNo, x, y, z, &celRect);
+ 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;
diff --git a/engines/sci/graphics/compare.h b/engines/sci/graphics/compare.h
index 348d5ef723..be461cdc5b 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 {
diff --git a/engines/sci/graphics/controls.cpp b/engines/sci/graphics/controls.cpp
index 26af9741c2..ff5a91eed4 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"
diff --git a/engines/sci/graphics/coordadjuster.cpp b/engines/sci/graphics/coordadjuster.cpp
index 422df52f27..9481a68f13 100644
--- a/engines/sci/graphics/coordadjuster.cpp
+++ b/engines/sci/graphics/coordadjuster.cpp
@@ -26,6 +26,7 @@
#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"
diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp
index 2f8393f9ac..e1c05c97da 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;
}
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,21 +276,8 @@ 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;
}
@@ -333,7 +327,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..7acd14acd9 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();
@@ -74,7 +74,7 @@ private:
GfxScreen *_screen;
GfxPalette *_palette;
GfxCoordAdjuster *_coordAdjuster;
- SciEvent *_event;
+ EventManager *_event;
int _upscaledHires;
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/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..9ce4474ee3 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,7 +48,6 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd
: _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette), _paint32(paint32) {
_coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster;
- _highPlanePri = 0;
}
GfxFrameout::~GfxFrameout() {
@@ -54,30 +55,20 @@ 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;
+ sortPlanes();
}
void GfxFrameout::kernelUpdatePlane(reg_t object) {
+ sortPlanes();
}
void GfxFrameout::kernelDeletePlane(reg_t object) {
- for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) {
- if (_planes[planeNr] == object) {
- _planes.remove_at(planeNr);
- break;
+ for (Common::List<reg_t>::iterator it = _planes.begin(); it != _planes.end(); it++) {
+ if (object == *it) {
+ _planes.erase(it);
+ return;
}
}
-
- // Recalculate highPlanePri
- _highPlanePri = 0;
-
- for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) {
- int16 planePri = readSelectorValue(_segMan, _planes[planeNr], SELECTOR(priority)) & 0xFFFF;
- if (planePri > _highPlanePri)
- _highPlanePri = planePri;
- }
}
void GfxFrameout::kernelAddScreenItem(reg_t object) {
@@ -95,73 +86,102 @@ void GfxFrameout::kernelDeleteScreenItem(reg_t object) {
}
int16 GfxFrameout::kernelGetHighPlanePri() {
- return _highPlanePri;
+ sortPlanes();
+ return readSelectorValue(g_sci->getEngineState()->_segMan, _planes.back(), SELECTOR(priority));
}
bool sortHelper(const FrameoutEntry* entry1, const FrameoutEntry* entry2) {
return (entry1->priority == entry2->priority) ? (entry1->y < entry2->y) : (entry1->priority < entry2->priority);
}
+bool planeSortHelper(const reg_t entry1, const reg_t entry2) {
+ SegManager *segMan = g_sci->getEngineState()->_segMan;
+
+ uint16 plane1Priority = readSelectorValue(segMan, entry1, SELECTOR(priority));
+ uint16 plane2Priority = readSelectorValue(segMan, entry2, SELECTOR(priority));
+
+ if (plane1Priority == 0xffff)
+ return true;
+
+ if (plane2Priority == 0xffff)
+ return false;
+
+ return plane1Priority < plane2Priority;
+}
+
+void GfxFrameout::sortPlanes() {
+ // First, remove any invalid planes
+ for (Common::List<reg_t>::iterator it = _planes.begin(); it != _planes.end();) {
+ if (!_segMan->isObject(*it))
+ 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 = (FrameoutEntry *)malloc(_screenItems.size() * sizeof(FrameoutEntry));
+
+ const SciGameId gameId = g_sci->getGameId();
- for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) {
- planeObject = _planes[planeNr];
- planePriority = readSelectorValue(_segMan, planeObject, SELECTOR(priority));
+ for (Common::List<reg_t>::iterator it = _planes.begin(); it != _planes.end(); it++) {
+ reg_t planeObject = *it;
+ uint16 planePriority = readSelectorValue(_segMan, planeObject, SELECTOR(priority));
- if (planePriority == -1) // Plane currently not meant to be shown
+ if (planePriority == 0xffff) // Plane currently not meant to be shown
continue;
+ Common::Rect planeRect;
planeRect.top = readSelectorValue(_segMan, planeObject, SELECTOR(top));
planeRect.left = readSelectorValue(_segMan, planeObject, SELECTOR(left));
planeRect.bottom = readSelectorValue(_segMan, planeObject, SELECTOR(bottom));
planeRect.right = readSelectorValue(_segMan, planeObject, SELECTOR(right));
- planeResY = readSelectorValue(_segMan, planeObject, SELECTOR(resY));
- planeResX = readSelectorValue(_segMan, planeObject, SELECTOR(resX));
+ int16 planeResY = readSelectorValue(_segMan, planeObject, SELECTOR(resY));
+ int16 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) {
+ byte planeBack = readSelectorValue(_segMan, planeObject, SELECTOR(back));
+ if (planeBack)
_paint32->fillRect(planeRect, planeBack);
- }
- planePictureNr = readSelectorValue(_segMan, planeObject, SELECTOR(picture));
+ GuiResourceId planePictureNr = readSelectorValue(_segMan, planeObject, SELECTOR(picture));
+ GfxPicture *planePicture = 0;
+ int16 planePictureCels = 0;
+
if ((planePictureNr != 0xFFFF) && (planePictureNr != 0xFFFE)) {
planePicture = new GfxPicture(_resMan, _coordAdjuster, 0, _screen, _palette, planePictureNr, false);
planePictureCels = planePicture->getSci32celCount();
_coordAdjuster->pictureSetDisplayArea(planeRect);
+ _palette->drewPicture(planePictureNr);
}
// 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,6 +191,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 (gameId == GID_GK1) {
+ if ((itemEntry->viewId == 11000) && (itemEntry->loopNo == 0) && (itemEntry->celNo == 0) && (itemEntry->priority == 1)) {
+ itemEntry->priority = 0; // HACK for gk1 hires main menu
+ }
+ if ((itemEntry->viewId == 10100) && (itemEntry->priority == 0)) {
+ itemEntry->priority = 1; // HACK for gk1 hires main menu
+ }
+ }
itemEntry->signal = readSelectorValue(_segMan, itemObject, SELECTOR(signal));
itemEntry->scaleX = readSelectorValue(_segMan, itemObject, SELECTOR(scaleX));
itemEntry->scaleY = readSelectorValue(_segMan, itemObject, SELECTOR(scaleY));
@@ -181,8 +209,9 @@ void GfxFrameout::kernelFrameout() {
itemEntry->y += planeRect.top;
itemEntry->x += planeRect.left;
- if (itemEntry->priority == 0)
- itemEntry->priority = itemEntry->y;
+ if (!(itemEntry->signal & 0x0010)) { // kSignalFixedPriority
+ // TODO: Change priority of this item
+ }
itemList.push_back(itemEntry);
itemEntry++;
@@ -194,12 +223,10 @@ void GfxFrameout::kernelFrameout() {
Common::sort(itemList.begin(), itemList.end(), sortHelper);
// Now display itemlist
- planePictureCel = 0;
-
+ int16 planePictureCel = 0;
itemEntry = itemData;
- FrameoutList::iterator listIterator = itemList.begin();
- FrameoutList::iterator listEnd = itemList.end();
- while (listIterator != listEnd) {
+
+ for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) {
itemEntry = *listIterator;
if (planePicture) {
while ((planePictureCel <= itemEntry->priority) && (planePictureCel < planePictureCels)) {
@@ -207,63 +234,72 @@ void GfxFrameout::kernelFrameout() {
planePictureCel++;
}
}
+
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);
+ if (view->isSci2Hires())
+ _screen->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x);
- if (itemEntry->celRect.top < 0 || itemEntry->celRect.top >= _screen->getHeight()) {
- listIterator++;
- continue;
+ 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);
+
+ int16 screenHeight = _screen->getHeight();
+ int16 screenWidth = _screen->getWidth();
+ if (view->isSci2Hires()) {
+ screenHeight = _screen->getDisplayHeight();
+ screenWidth = _screen->getDisplayWidth();
}
- if (itemEntry->celRect.left < 0 || itemEntry->celRect.left >= _screen->getWidth()) {
- listIterator++;
+ if (itemEntry->celRect.top < 0 || itemEntry->celRect.top >= screenHeight)
+ continue;
+
+ if (itemEntry->celRect.left < 0 || itemEntry->celRect.left >= screenWidth)
continue;
- }
Common::Rect clipRect;
clipRect = itemEntry->celRect;
- clipRect.clip(planeRect);
+ if (view->isSci2Hires()) {
+ Common::Rect upscaledPlaneRect = planeRect;
+ _screen->adjustToUpscaledCoordinates(upscaledPlaneRect.top, upscaledPlaneRect.left);
+ _screen->adjustToUpscaledCoordinates(upscaledPlaneRect.bottom, upscaledPlaneRect.right);
+ clipRect.clip(upscaledPlaneRect);
+ } else {
+ clipRect.clip(planeRect);
+ }
if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128))
- view->draw(itemEntry->celRect, clipRect, clipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, false);
+ view->draw(itemEntry->celRect, clipRect, clipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires());
else
view->drawScaled(itemEntry->celRect, clipRect, clipRect, 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) {
+ Common::String text = _segMan->getString(readSelector(_segMan, itemEntry->object, SELECTOR(text)));
+ 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));
+ uint16 curX = itemEntry->x;
+ uint16 curY = itemEntry->y;
+ 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);
@@ -273,6 +309,7 @@ void GfxFrameout::kernelFrameout() {
planePicture = 0;
}
}
+
free(itemData);
_screen->copyToScreen();
}
diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h
index 36c02af278..e4568ad602 100644
--- a/engines/sci/graphics/frameout.h
+++ b/engines/sci/graphics/frameout.h
@@ -41,10 +41,14 @@ struct FrameoutEntry {
int16 scaleY;
Common::Rect celRect;
};
+
typedef Common::List<FrameoutEntry *> FrameoutList;
class GfxCache;
+class GfxCoordAdjuster32;
class GfxPaint32;
+class GfxPalette;
+class GfxScreen;
/**
* Frameout class, kFrameout and relevant functions for SCI32 games
*/
@@ -71,8 +75,9 @@ private:
GfxPaint32 *_paint32;
Common::Array<reg_t> _screenItems;
- Common::Array<reg_t> _planes;
- int16 _highPlanePri;
+ Common::List<reg_t> _planes;
+
+ void sortPlanes();
};
} // 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/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..bfe58e03d5 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 == "+") {
@@ -377,7 +382,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;
@@ -392,7 +397,8 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) {
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 +407,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:
@@ -439,9 +445,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;
@@ -562,7 +568,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 +632,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 +693,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 +718,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 +809,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 +838,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 +849,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.h b/engines/sci/graphics/paint.h
index f1342d55e5..75a17461d4 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 {
diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp
index ff4f3bec52..90b05c68a6 100644
--- a/engines/sci/graphics/paint16.cpp
+++ b/engines/sci/graphics/paint16.cpp
@@ -42,13 +42,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 +75,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 +107,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 +127,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 +137,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 +317,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 +332,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;
}
@@ -374,7 +383,8 @@ void GfxPaint16::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, b
}
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
+ // 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);
} else {
@@ -382,19 +392,19 @@ void GfxPaint16::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo,
}
}
-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 +416,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 +428,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,6 +458,8 @@ 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, 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) {
@@ -457,7 +470,8 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) {
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
@@ -512,8 +526,24 @@ 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
+ case SCI_DISPLAY_DUMMY1:
+ case SCI_DISPLAY_DUMMY2:
+ if (!((g_sci->getGameId() == GID_LONGBOW) && (g_sci->isDemo())))
+ error("Unknown kDisplay argument %X", displayArg);
+ if (displayArg == SCI_DISPLAY_DUMMY2) {
+ if (argc) {
+ argc--; argv++;
+ } else {
+ error("No parameter left for kDisplay(0x73)");
+ }
+ }
+ break;
default:
- warning("Unknown kDisplay argument %X", displayArg);
+ if ((g_sci->getGameId() == GID_ISLANDBRAIN) && (g_sci->getEngineState()->currentRoomNumber() == 300))
+ break; // WORKAROUND: we are called there with an forwarded 0 as additional parameter (script bug)
+ error("Unknown kDisplay argument %X", displayArg);
break;
}
}
@@ -540,14 +570,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;
@@ -562,12 +598,33 @@ void GfxPaint16::kernelShakeScreen(uint16 shakeCount, uint16 directions) {
_screen->setVerticalShakePos(10);
// TODO: horizontal shakes
g_system->updateScreen();
- _gui->wait(3);
+ g_sci->getEngineState()->wait(3);
+
if (directions & SCI_SHAKE_DIRECTION_VERTICAL)
_screen->setVerticalShakePos(0);
+
g_system->updateScreen();
- _gui->wait(3);
+ g_sci->getEngineState()->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..4c3ac255c4 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);
@@ -76,26 +75,30 @@ public:
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 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..957199f8b9 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,39 @@ 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);
- }
+
+ // Pseudo-WORKAROUND
+ // Quest for Glory 3 demo, Eco Quest 1 demo, Laura Bow 2 demo, Police Quest 1 vga and all Nick's Picks
+ // all use an inbetween interpreter, some parts are SCI1.1, some parts are SCI1
+ // It's not using the SCI1.1 palette merging (copying over all the colors) but the real merging
+ // 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() {
}
+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 +99,16 @@ 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
+ warning("GfxPalette::createFromData() - not enough bytes in resource, expected palette header");
+ return;
+ }
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 +123,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 +136,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 +213,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 +371,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 +382,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 +409,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 +447,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) {
@@ -414,7 +485,21 @@ void GfxPalette::kernelAnimateSet() {
}
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 +528,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..6af1d5a490 100644
--- a/engines/sci/graphics/palette.h
+++ b/engines/sci/graphics/palette.h
@@ -36,20 +36,26 @@ class Screen;
*/
class GfxPalette {
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);
@@ -59,25 +65,46 @@ public:
void kernelAnimateSet();
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;
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..7cd37b6f46 100644
--- a/engines/sci/graphics/picture.cpp
+++ b/engines/sci/graphics/picture.cpp
@@ -109,7 +109,7 @@ void GfxPicture::drawSci11Vga() {
Palette palette;
// Create palette and set it
- _palette->createFromData(inbuffer + palette_data_ptr, &palette);
+ _palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette);
_palette->set(&palette, true);
// display Cel-data
@@ -147,7 +147,7 @@ void GfxPicture::drawSci32Vga(int16 celNo) {
if ((celNo == -1) || (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) {
@@ -437,7 +437,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,7 +532,7 @@ 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
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..611db1061a 100644
--- a/engines/sci/graphics/ports.cpp
+++ b/engines/sci/graphics/ports.cpp
@@ -54,11 +54,10 @@ GfxPorts::~GfxPorts() {
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,20 +84,44 @@ 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:
+ if (getSciVersion() == SCI_VERSION_1_EARLY)
+ offTop = 0;
+ 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;
@@ -214,7 +237,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;
}
@@ -228,6 +251,7 @@ 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!)
+ // same happens very often in lsl5, sierra sci didnt fix it but it looked awful
warning("fixing too large window, given left&right was %d, %d", dims.left, dims.right);
r.left = 0;
r.right = _screen->getWidth() - 1;
@@ -496,6 +520,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) {
diff --git a/engines/sci/graphics/ports.h b/engines/sci/graphics/ports.h
index c8ce6b3470..818f92f44f 100644
--- a/engines/sci/graphics/ports.h
+++ b/engines/sci/graphics/ports.h
@@ -45,7 +45,7 @@ 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 kernelSetActive(uint16 portId);
Common::Rect kernelGetPicWindow(int16 &picTop, int16 &picLeft);
@@ -102,7 +102,6 @@ private:
typedef Common::List<Port *> PortList;
SegManager *_segMan;
- SciGui *_gui;
GfxPaint16 *_paint16;
GfxScreen *_screen;
GfxText16 *_text16;
diff --git a/engines/sci/graphics/robot.cpp b/engines/sci/graphics/robot.cpp
index 2f711eb58a..d926e037f4 100644
--- a/engines/sci/graphics/robot.cpp
+++ b/engines/sci/graphics/robot.cpp
@@ -31,17 +31,17 @@
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);
}
-Robot::~Robot() {
+GfxRobot::~GfxRobot() {
_resMan->unlockResource(_resource);
}
-void Robot::initData(GuiResourceId resourceId) {
+void GfxRobot::initData(GuiResourceId resourceId) {
_resource = _resMan->findResource(ResourceId(kResourceTypeRobot, resourceId), true);
if (!_resource) {
error("robot resource %d not found", resourceId);
@@ -158,7 +158,7 @@ void Robot::initData(GuiResourceId resourceId) {
// 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..80dae95f95 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();
diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp
index 0e054d5a76..488bb83ab3 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_QFG1)
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
@@ -557,19 +633,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 +655,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..f1e3d028a8 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,15 @@ public:
void bitsGetRect(byte *memoryPtr, Common::Rect *destRect);
void bitsRestore(byte *memoryPtr);
- void setPalette(Palette*pal);
+ void getPalette(Palette *pal);
+ void setPalette(Palette *pal);
void setVerticalShakePos(uint16 shakePos);
- 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);
@@ -138,27 +146,34 @@ private:
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..4aa2346aed 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,9 +133,11 @@ 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;
@@ -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)
@@ -453,11 +434,14 @@ void GfxText16::Box(const char *text, int16 bshow, const Common::Rect &rect, Tex
_ports->penColor(orgPenColor);
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;
@@ -478,7 +462,8 @@ void GfxText16::Draw_String(const char *text) {
_ports->penColor(orgPenColor);
}
-// 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 +473,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..71b602d116 100644
--- a/engines/sci/graphics/text16.h
+++ b/engines/sci/graphics/text16.h
@@ -48,8 +48,6 @@ 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);
@@ -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..c1f626449f 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,7 +407,8 @@ 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
+// 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;
@@ -440,8 +447,12 @@ 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:
@@ -461,8 +472,12 @@ 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:
@@ -503,7 +518,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,7 +535,8 @@ 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);
@@ -531,7 +548,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 +565,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 +578,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 +608,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..788cefabca 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);
@@ -92,7 +92,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..93df45820c 100644
--- a/engines/sci/graphics/view.cpp
+++ b/engines/sci/graphics/view.cpp
@@ -62,6 +62,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 +76,28 @@ 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;
+
+ // 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 +112,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;
}
@@ -169,12 +188,14 @@ void GfxView::initData(GuiResourceId resourceId) {
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 = 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
+ // FIXME: After LoopCount there is another byte and its set for view 50
+ // within Laura Bow 2 CD, check what it means.
loopData = _resourceData + headerSize;
loopSize = _resourceData[12];
@@ -183,7 +204,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;
}
@@ -221,6 +242,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)
@@ -236,65 +260,68 @@ 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;
+}
+
+bool GfxView::isSci2Hires() {
+ return _isSci2Hires;
+}
+
+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;
+ 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) {
+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 +336,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 +381,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 +440,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 +456,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 +484,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 +498,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 +528,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 +540,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 +556,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 +585,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;
if (_embeddedPal) {
// Merge view palette in...
@@ -590,6 +633,7 @@ void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect
scaledPixel = scaledPixelNo = prevScaledPixelNo = 0;
while (pixelNo < celHeight) {
scaledPixelNo = scaledPixel >> 7;
+ assert(scaledPixelNo < ARRAYSIZE(scalingY));
if (prevScaledPixelNo < scaledPixelNo)
memset(&scalingY[prevScaledPixelNo], pixelNo, scaledPixelNo - prevScaledPixelNo);
scalingY[scaledPixelNo] = pixelNo;
@@ -606,6 +650,7 @@ void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect
scaledPixel = scaledPixelNo = prevScaledPixelNo = 0;
while (pixelNo < celWidth) {
scaledPixelNo = scaledPixel >> 7;
+ assert(scaledPixelNo < ARRAYSIZE(scalingX));
if (prevScaledPixelNo < scaledPixelNo)
memset(&scalingX[prevScaledPixelNo], pixelNo, scaledPixelNo - prevScaledPixelNo);
scalingX[scaledPixelNo] = pixelNo;
@@ -620,27 +665,25 @@ void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect
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;
+
+ // Happens in SQ6, first room
+ if (offsetX < 0 || offsetY < 0)
+ return;
- 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);
+ 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..6eb1830b99 100644
--- a/engines/sci/graphics/view.h
+++ b/engines/sci/graphics/view.h
@@ -60,20 +60,21 @@ 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 isSci2Hires();
+
private:
void initData(GuiResourceId resourceId);
void unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount);
@@ -86,12 +87,16 @@ private:
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;
};
diff --git a/engines/sci/module.mk b/engines/sci/module.mk
index a2cfd38f95..85988b8f1b 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 \
@@ -44,7 +43,6 @@ MODULE_OBJS := \
graphics/cursor.o \
graphics/font.o \
graphics/fontsjis.o \
- graphics/gui.o \
graphics/maciconbar.o \
graphics/menu.o \
graphics/paint.o \
@@ -69,9 +67,6 @@ MODULE_OBJS := \
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
@@ -79,7 +74,6 @@ 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/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp
index 00448f5d51..e48a9cdfda 100644
--- a/engines/sci/parser/vocabulary.cpp
+++ b/engines/sci/parser/vocabulary.cpp
@@ -33,59 +33,6 @@
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) {
_parserRules = NULL;
_vocabVersion = kVocabularySCI0;
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index 400f0b1e67..2958ca1e3b 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 {
@@ -111,7 +114,7 @@ static const char *resourceTypeNames[] = {
"memory", "vocab", "font", "cursor",
"patch", "bitmap", "palette", "cdaudio",
"audio", "sync", "message", "map", "heap",
- "audio36", "sync36", "", "", "robot"
+ "audio36", "sync36", "", "", "robot", "vmd"
};
static const char *resourceTypeSuffixes[] = {
@@ -119,7 +122,7 @@ static const char *resourceTypeSuffixes[] = {
" ", "voc", "fon", "cur", "pat",
"bit", "pal", "cda", "aud", "syn",
"msg", "map", "hep", "aud", "syn",
- "trn", " ", "rbt"
+ "trn", " ", "rbt", "vmd"
};
const char *getResourceTypeName(ResourceType restype) {
@@ -130,7 +133,7 @@ const char *getResourceTypeName(ResourceType restype) {
}
//-- Resource main functions --
-Resource::Resource() {
+Resource::Resource(ResourceId id) : _id(id) {
data = NULL;
size = 0;
_fileOffset = 0;
@@ -143,7 +146,7 @@ Resource::Resource() {
Resource::~Resource() {
delete[] data;
- if (_source && _source->source_type == kSourcePatch)
+ if (_source && _source->getSourceType() == kSourcePatch)
delete _source;
}
@@ -154,102 +157,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 +235,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 +265,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 +319,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: %d %d", 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 +464,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 +477,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 +509,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 +518,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
@@ -524,7 +528,7 @@ int ResourceManager::addAppropriateSources() {
addPatchDir(".");
if (Common::File::exists("message.map"))
- addSource(addExternalMap("message.map"), kSourceVolume, "resource.msg", 0);
+ addSource(new VolumeResourceSource("resource.msg", addExternalMap("message.map"), 0));
return 1;
}
@@ -568,7 +572,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 +587,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,12 +602,12 @@ 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;
}
@@ -615,38 +619,39 @@ 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);
+}
+
+
void ResourceManager::freeResourceSources() {
for (Common::List<ResourceSource *>::iterator it = _sources.begin(); it != _sources.end(); ++it)
delete *it;
@@ -655,13 +660,6 @@ void ResourceManager::freeResourceSources() {
}
ResourceManager::ResourceManager() {
- addAppropriateSources();
- init();
-}
-
-ResourceManager::ResourceManager(const Common::FSList &fslist) {
- addAppropriateSources(fslist);
- init();
}
void ResourceManager::init() {
@@ -716,7 +714,7 @@ 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");
}
}
@@ -795,7 +793,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 +811,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 +874,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 +882,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 +907,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 +964,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;
}
@@ -1068,41 +1066,41 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() {
// version-agnostic patch application
void ResourceManager::processPatch(ResourceSource *source, ResourceType resourceType, uint16 resourceNr, uint32 tuple) {
Common::SeekableReadStream *fileStream = 0;
- Resource *newrsc;
+ Resource *newrsc = 0;
ResourceId resId = ResourceId(resourceType, resourceNr, tuple);
- byte patchType, patchDataOffset;
- int fsize;
+ ResourceType checkForType = resourceType;
// base36 encoded patches (i.e. audio36 and sync36) have the same type as their non-base36 encoded counterparts
- if (resourceType == kResourceTypeAudio36)
- resourceType = kResourceTypeAudio;
-
- if (resourceType == kResourceTypeSync36)
- resourceType = kResourceTypeSync;
+ if (checkForType == kResourceTypeAudio36)
+ checkForType = kResourceTypeAudio;
+ else if (checkForType == kResourceTypeSync36)
+ checkForType = kResourceTypeSync;
- if (source->resourceFile) {
- fileStream = source->resourceFile->createReadStream();
+ 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;
- patchDataOffset = fileStream->readByte();
+ byte patchType = fileStream->readByte() & 0x7F;
+ byte patchDataOffset = fileStream->readByte();
delete fileStream;
- if (patchType != resourceType) {
- 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
@@ -1118,35 +1116,27 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource
patchDataOffset = 8;
break;
default:
- warning("Resource patch unsupported special case %X", patchDataOffset & 0x7F);
+ error("Resource patch unsupported special case %X", patchDataOffset & 0x7F);
return;
}
}
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(), patchDataOffset + 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 - patchDataOffset - 2;
+ 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
@@ -1176,42 +1166,61 @@ 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();
- if (inputName.hasPrefix("BOOT")) // skip bootdisk.*
- continue;
-
inputName.deleteChar(0); // delete the first character (type)
inputName.deleteChar(7); // delete the dot
// The base36 encoded resource contains the following:
// uint16 resourceId, byte noun, byte verb, byte cond, byte seq
- uint16 resourceNr = strtol(Common::String(inputName.c_str(), 3).c_str(), 0, 36); // 3 characters
- byte noun = strtol(Common::String(inputName.c_str() + 3, 2).c_str(), 0, 36); // 2 characters
- byte verb = strtol(Common::String(inputName.c_str() + 5, 2).c_str(), 0, 36); // 2 characters
- byte cond = strtol(Common::String(inputName.c_str() + 7, 2).c_str(), 0, 36); // 2 characters
- byte seq = strtol(Common::String(inputName.c_str() + 9, 1).c_str(), 0, 36); // 1 character
- 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());
- */
-
- psrcPatch = new ResourceSource;
- psrcPatch->source_type = kSourcePatch;
- psrcPatch->location_name = name;
- psrcPatch->resourceFile = 0;
- processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.tuple);
+ 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
@@ -1237,10 +1246,12 @@ void ResourceManager::readResourcePatches(ResourceSource *source) {
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
bool bAdd = false;
name = (*x)->getName();
+
// SCI1 scheme
if (isdigit(name[0])) {
- resourceNr = 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);
@@ -1252,10 +1263,7 @@ void ResourceManager::readResourcePatches(ResourceSource *source) {
}
if (bAdd) {
- psrcPatch = new ResourceSource;
- psrcPatch->source_type = kSourcePatch;
- psrcPatch->location_name = name;
- psrcPatch->resourceFile = 0;
+ psrcPatch = new PatchResourceSource(name);
processPatch(psrcPatch, (ResourceType)i, resourceNr);
}
}
@@ -1264,18 +1272,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;
}
@@ -1291,7 +1298,7 @@ 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)
@@ -1302,9 +1309,8 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) {
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");
@@ -1312,12 +1318,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());
@@ -1327,15 +1332,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;
}
@@ -1382,22 +1386,17 @@ 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);
// 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;
+ addResource(resId, findVolume(map, volume_nr + map->_volumeNumber), off);
}
}
}
@@ -1438,11 +1437,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;
@@ -1457,11 +1456,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)
@@ -1472,41 +1471,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(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(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
@@ -1515,7 +1517,7 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream
uint32 wCompression, szUnpacked;
ResourceType type;
- switch (_volVersion) {
+ switch (volVersion) {
case kResVersionSci0Sci1Early:
case kResVersionSci1Middle:
w = file->readUint16LE();
@@ -1542,8 +1544,8 @@ 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;
@@ -1565,8 +1567,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) {
@@ -1602,15 +1604,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;
@@ -1636,18 +1638,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() {
@@ -1661,7 +1663,7 @@ ResourceCompression ResourceManager::getViewCompression() {
if (!res)
continue;
- if (res->_source->source_type != kSourceVolume)
+ if (res->_source->getSourceType() != kSourceVolume)
continue;
fileStream = getVolumeFile(res->_source);
@@ -1673,13 +1675,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)
@@ -1697,6 +1699,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
@@ -1752,6 +1758,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;
}
@@ -1862,7 +1869,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;
@@ -1911,15 +1918,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");
@@ -1939,12 +1949,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 533c81bdf5..f66b5b3956 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,
@@ -109,6 +98,7 @@ enum ResourceType {
kResourceTypeUnknown1, // Translation, currently unsupported
kResourceTypeUnknown2,
kResourceTypeRobot,
+ kResourceTypeVMD,
kResourceTypeInvalid,
// Mac-only resources, these resource types are self-defined
@@ -121,152 +111,199 @@ enum ResourceType {
const char *getResourceTypeName(ResourceType restype);
-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;
+enum ResVersion {
+ kResVersionUnknown,
+ kResVersionSci0Sci1Early,
+ kResVersionSci1Middle,
+ kResVersionSci1Late,
+ kResVersionSci11,
+ kResVersionSci11Mac,
+ kResVersionSci32
};
+class ResourceManager;
+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 < kResourceTypeMacPict || 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.%i", 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, "(%i, %i, %i, %i)", _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;
+
+// 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(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;
+
+ 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;
+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,27 +315,30 @@ public:
ViewType getViewType() const { return _viewType; }
const char *getMapVersionDesc() const { return versionDescription(_mapVersion); }
const char *getVolVersionDesc() const { return versionDescription(_volVersion); }
+ ResVersion getVolVersion() const { return _volVersion; }
/**
* Adds the appropriate GM patch from the Sierra MIDI utility as 4.pat, without
* requiring the user to rename the file to 4.pat. Thus, the original Sierra
* archive can be extracted in the extras directory, and the GM patches can be
- * applied per game, if applicable
+ * applied per game, if applicable.
*/
- void addNewGMPatch(const Common::String &gameId);
+ void addNewGMPatch(SciGameId gameId);
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().
*/
@@ -325,85 +365,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 +432,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 +453,15 @@ protected:
/**
* Reads patch files from a local directory.
*/
- void readResourcePatches(ResourceSource *source);
-#ifdef ENABLE_SCI32
- void readResourcePatchesBase36(ResourceSource *source);
-#endif
+ 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 +492,7 @@ public:
uint16 prio;
uint16 size;
byte *data;
+ uint16 curPos;
long time;
byte prev;
};
@@ -515,7 +517,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 +524,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..13aa81cb24 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();
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();
+ 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 {
@@ -261,27 +259,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 +291,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 +301,25 @@ 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 {
- // 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 +347,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 +377,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 +389,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 +407,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 +424,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 +436,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 +460,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 +470,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 +492,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:
@@ -537,6 +554,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 +566,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..45421dd722
--- /dev/null
+++ b/engines/sci/resource_intern.h
@@ -0,0 +1,193 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along 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
+};
+
+
+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);
+};
+
+} // End of namespace Sci
+
+#endif // SCI_RESOURCE_INTERN_H
diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp
index 929bdf3307..1ebc6a2ba3 100644
--- a/engines/sci/sci.cpp
+++ b/engines/sci/sci.cpp
@@ -36,22 +36,32 @@
#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/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 +71,22 @@ 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;
+ _eventMan = 0;
+ _console = 0;
// Set up the engine specific debug levels
DebugMan.addDebugChannel(kDebugLevelError, "Error", "Script error debugging");
@@ -78,10 +97,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 +108,24 @@ 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, "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, "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,14 +133,35 @@ 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;
}
@@ -135,166 +171,289 @@ Common::Error SciEngine::run() {
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;
}
+*/
- SegManager *segMan = new SegManager(_resMan);
-
- // Scale the screen, if needed
- int 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 (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
- }
-
- // 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;
-
- // Initialize graphics-related parts
- GfxScreen *screen = 0;
+ // Reset, so that error()s before SoundCommandParser is initialized wont cause a crash
+ _soundCmd = NULL;
- // invokes initGraphics()
- if (_resMan->detectHires())
- screen = new GfxScreen(_resMan, 640, 480);
- else
- screen = new GfxScreen(_resMan, 320, 200, upscaledHires);
+ // Add the after market GM patches for the specified game, if they exist
+ _resMan->addNewGMPatch(_gameId);
+ _gameObj = _resMan->findGameObject();
- if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1)
- _gfxMacIconBar = new GfxMacIconBar();
+ SegManager *segMan = new SegManager(_resMan);
- GfxPalette *palette = new GfxPalette(_resMan, screen);
- GfxCache *cache = new GfxCache(_resMan, screen, palette);
- GfxCursor *cursor = new GfxCursor(_resMan, palette, screen);
+ // Initialize the game screen
+ _gfxScreen = new GfxScreen(_resMan);
+ _gfxScreen->debugUnditherSetState(ConfMan.getBool("undither"));
// 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) : NULL;
_audio = new AudioPlayer(_resMan);
+ _gamestate = new EngineState(segMan);
+ _eventMan = new EventManager(_resMan->detectFontExtended());
- _features = new GameFeatures(segMan, _kernel);
+ // 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;
+ }
- _gamestate = new EngineState(segMan);
+ script_adjust_opcode_formats();
- _gamestate->_event = new SciEvent(_resMan);
+ // Must be called after game_init(), as they use _features
+ _kernel->loadKernelNames(_features);
+ _soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, _features->detectDoSoundType());
- if (script_init_engine(_gamestate))
- return Common::kUnknownError;
+ syncSoundSettings();
-#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;
+ // Initialize all graphics related subsystems
+ initGraphics();
+
+ debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()));
+
+ // 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);
+
+ // 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;
+ }
}
-#endif
- _gfxPalette = palette;
- _gfxScreen = screen;
- _gfxCache = cache;
- _gfxCursor = cursor;
+ runGame();
- if (game_init(_gamestate)) { /* Initialize */
- warning("Game initialization failed: Aborting...");
- // TODO: Add an "init failed" error?
- return Common::kUnknownError;
+ ConfMan.flushToDisk();
+
+ return Common::kNoError;
+}
+
+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);
+
+ _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;
}
- // Add the after market GM patches for the specified game, if they exist
- _resMan->addNewGMPatch(getGameID());
+ _gamestate->initGlobals();
- script_adjust_opcode_formats(_gamestate);
- _kernel->loadKernelNames(getGameID());
+ if (_gamestate->abortScriptProcessing == kAbortRestartGame && _gfxMenu)
+ _gfxMenu->reset();
- SciVersion soundVersion = _features->detectDoSoundType();
+ _gamestate->_segMan->initSysStrings();
- _gamestate->_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, soundVersion);
+ _gamestate->r_acc = _gamestate->r_prev = NULL_REG;
- screen->debugUnditherSetState(ConfMan.getBool("undither"));
+ _gamestate->_executionStack.clear(); // Start without any execution stack
+ _gamestate->executionStackBase = -1; // No vm is running yet
+ _gamestate->_executionStackPosChanged = false;
-#ifdef USE_OLD_MUSIC_FUNCTIONS
- if (game_init_sound(_gamestate, 0, soundVersion)) {
- warning("Game initialization failed: Error in sound subsystem. Aborting...");
- return Common::kUnknownError;
+ _gamestate->abortScriptProcessing = kAbortNone;
+ _gamestate->gameWasRestarted = false;
+
+ _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;
}
-#endif
- syncSoundSettings();
+ // Reset parser
+ if (_vocabulary) {
+ _vocabulary->parserIsValid = false; // Invalidate parser
+ _vocabulary->parser_event = NULL_REG; // Invalidate parser event
+ _vocabulary->parser_base = make_reg(_gamestate->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE);
+ }
+ _gamestate->gameStartTime = _gamestate->lastWaitTime = _gamestate->_screenUpdateTime = g_system->getMillis();
+
+ srand(g_system->getMillis()); // Initialize random number generator
+
+ // Load game language into printLang property of game object
+ setSciLanguage();
+
+ return true;
+}
+
+void SciEngine::initGraphics() {
+
+ // Reset all graphics objects
+ _gfxAnimate = 0;
+ _gfxCache = 0;
+ _gfxCompare = 0;
+ _gfxControls = 0;
+ _gfxCoordAdjuster = 0;
+ _gfxCursor = 0;
+ _gfxMacIconBar = 0;
+ _gfxMenu = 0;
+ _gfxPaint = 0;
+ _gfxPaint16 = 0;
+ _gfxPalette = 0;
+ _gfxPorts = 0;
+ _gfxText16 = 0;
+ _gfxTransitions = 0;
#ifdef ENABLE_SCI32
- if (_gui32)
- _gui32->init();
- else
+ _gfxFrameout = 0;
+ _gfxPaint32 = 0;
#endif
- _gui->init(_features->usesOldGfxFunctions());
- debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion()));
+ if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1)
+ _gfxMacIconBar = new GfxMacIconBar();
- // Check whether loading a savestate was requested
- if (ConfMan.hasKey("save_slot")) {
- _gamestate->loadFromLauncher = ConfMan.getInt("save_slot");
+ bool paletteMerging = true;
+ if (getSciVersion() >= SCI_VERSION_1_1) {
+ // there are some games that use inbetween SCI1.1 interpreter, so we have to detect if it's merging or copying
+ if (getSciVersion() == SCI_VERSION_1_1)
+ paletteMerging = _resMan->detectForPaletteMergingForSci11();
+ else
+ paletteMerging = false;
+ }
+
+ _gfxPalette = new GfxPalette(_resMan, _gfxScreen, paletteMerging);
+ _gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette);
+ _gfxCursor = new GfxCursor(_resMan, _gfxPalette, _gfxScreen);
+
+#ifdef ENABLE_SCI32
+ if (getSciVersion() >= SCI_VERSION_2) {
+ // SCI32 graphic objects creation
+ _gfxCoordAdjuster = new GfxCoordAdjuster32(_gamestate->_segMan);
+ _gfxCursor->init(_gfxCoordAdjuster, _eventMan);
+ _gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster);
+ _gfxPaint32 = new GfxPaint32(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette);
+ _gfxPaint = _gfxPaint32;
+ _gfxFrameout = new GfxFrameout(_gamestate->_segMan, g_sci->getResMan(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32);
} else {
- _gamestate->loadFromLauncher = -1;
+#endif
+ // SCI0-SCI1.1 graphic objects creation
+ _gfxPorts = new GfxPorts(_gamestate->_segMan, _gfxScreen);
+ _gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts);
+ _gfxCursor->init(_gfxCoordAdjuster, g_sci->getEventManager());
+ _gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster);
+ _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, g_sci->getResMan()->isVGA());
+ _gfxPaint16 = new GfxPaint16(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio);
+ _gfxPaint = _gfxPaint16;
+ _gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions);
+ _gfxText16 = new GfxText16(g_sci->getResMan(), _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen);
+ _gfxControls = new GfxControls(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen);
+ _gfxMenu = new GfxMenu(g_sci->getEventManager(), _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor);
+
+ _gfxMenu->reset();
+#ifdef ENABLE_SCI32
}
+#endif
- game_run(&_gamestate); // Run the game
+ if (_gfxPorts) {
+ _gfxPorts->init(_features->usesOldGfxFunctions(), _gfxPaint16, _gfxText16);
+ _gfxPaint16->init(_gfxAnimate, _gfxText16);
+ }
+ // Set default (EGA, amiga or resource 999) palette
+ _gfxPalette->setDefault();
+}
- game_exit(_gamestate);
+void SciEngine::initStackBaseWithSelector(Selector selector) {
+ _gamestate->stack_base[0] = make_reg(0, (uint16)selector);
+ _gamestate->stack_base[1] = NULL_REG;
- ConfMan.flushToDisk();
+ // Register the first element on the execution stack
+ if (!send_selector(_gamestate, _gameObj, _gameObj, _gamestate->stack_base, 2, _gamestate->stack_base)) {
+ _console->printObject(_gameObj);
+ error("initStackBaseWithSelector: error while registering the first selector in the call stack");
+ }
- delete _gamestate->_soundCmd;
- delete _gui;
-#ifdef ENABLE_SCI32
- delete _gui32;
-#endif
- delete _gfxPorts;
- delete _gfxCache;
- delete _gfxPalette;
- delete cursor;
- delete _gfxScreen;
- delete _gamestate->_event;
- delete segMan;
- delete _gamestate;
+}
- return Common::kNoError;
+void SciEngine::runGame() {
+ initStackBaseWithSelector(SELECTOR(play)); // Call the play selector
+
+ // Attach the debug console on game startup, if requested
+ if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup))
+ _console->attach();
+
+ do {
+ _gamestate->_executionStackPosChanged = false;
+ run_vm(_gamestate, (_gamestate->abortScriptProcessing == kAbortLoadGame));
+ exitGame();
+
+ if (_gamestate->abortScriptProcessing == kAbortRestartGame) {
+ _gamestate->_segMan->resetSegMan();
+ initGame();
+ initStackBaseWithSelector(SELECTOR(play));
+ _gamestate->gameWasRestarted = true;
+ } else if (_gamestate->abortScriptProcessing == kAbortLoadGame) {
+ _gamestate->abortScriptProcessing = kAbortNone;
+ initStackBaseWithSelector(SELECTOR(replay));
+ } else {
+ break; // exit loop
+ }
+ } while (true);
+}
+
+void SciEngine::exitGame() {
+ if (_gamestate->abortScriptProcessing != kAbortLoadGame) {
+ _gamestate->_executionStack.clear();
+ _audio->stopAllAudio();
+ g_sci->_soundCmd->clearPlayList();
+ }
+
+ // TODO Free parser segment here
+
+ // TODO Free scripts here
+
+ // Close all opened file handles
+ _gamestate->_fileHandles.clear();
+ _gamestate->_fileHandles.resize(5);
}
// Invoked by error() when a severe error occurs
GUI::Debugger *SciEngine::getDebugger() {
if (_gamestate) {
ExecStack *xs = &(_gamestate->_executionStack.back());
- xs->addr.pc.offset = g_debugState.old_pc_offset;
- xs->sp = g_debugState.old_sp;
+ xs->addr.pc.offset = _debugState.old_pc_offset;
+ xs->sp = _debugState.old_sp;
}
- g_debugState.runningStep = 0; // Stop multiple execution
- g_debugState.seeking = kDebugSeekNothing; // Stop special seeks
+ _debugState.runningStep = 0; // Stop multiple execution
+ _debugState.seeking = kDebugSeekNothing; // Stop special seeks
return _console;
}
@@ -304,7 +463,7 @@ Console *SciEngine::getSciDebugger() {
return _console;
}
-const char* SciEngine::getGameID() const {
+const char *SciEngine::getGameIdStr() const {
return _gameDescription->gameid;
}
@@ -316,12 +475,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,14 +488,12 @@ 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";
@@ -361,27 +514,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..c15f87e4e2 100644
--- a/engines/sci/sci.h
+++ b/engines/sci/sci.h
@@ -28,6 +28,8 @@
#include "engines/engine.h"
#include "common/util.h"
+#include "sci/engine/vm_types.h" // for Selector
+#include "sci/debug.h" // for DebugState
struct ADGameDescription;
@@ -41,9 +43,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 +50,8 @@ class Kernel;
class GameFeatures;
class Console;
class AudioPlayer;
+class SoundCommandParser;
+class EventManager;
class GfxAnimate;
class GfxCache;
@@ -58,14 +59,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 +85,89 @@ 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_MSASTROCHICKEN,
+ GID_PEPPER,
+ GID_PHANTASMAGORIA,
+ GID_PHANTASMAGORIA2,
+ GID_PQ1,
+ GID_PQ2,
+ GID_PQ3,
+ GID_PQ4,
+ GID_PQSWAT,
+ GID_QFG1,
+ 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 +186,6 @@ enum SciVersion {
SCI_VERSION_3 // LSL7, RAMA, Lighthouse
};
-enum MoveCountType {
- kMoveCountUninitialized,
- kIgnoreMoveCount,
- kIncrementMoveCount
-};
-
/** Supported languages */
enum kLanguage {
K_LANG_NONE = 0,
@@ -138,7 +202,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 +217,19 @@ 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::String getSavegameName(int nr) const;
Common::String getSavegamePattern() const;
@@ -176,6 +242,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 +261,14 @@ 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;
+ // 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 +280,60 @@ 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;
+ EventManager *_eventMan;
+ reg_t _gameObj; /**< Pointer to the game object */
Console *_console;
- OSystem *_system;
};
diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp
index 7ecce3b2a3..d9e9d2e8db 100644
--- a/engines/sci/sound/audio.cpp
+++ b/engines/sci/sound/audio.cpp
@@ -24,20 +24,21 @@
*/
#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/decoders/raw.h"
-#include "sound/decoders/wave.h"
+#include "sound/decoders/aiff.h"
#include "sound/decoders/flac.h"
#include "sound/decoders/mp3.h"
+#include "sound/decoders/raw.h"
#include "sound/decoders/vorbis.h"
+#include "sound/decoders/wave.h"
namespace Sci {
@@ -45,6 +46,7 @@ AudioPlayer::AudioPlayer(ResourceManager *resMan) : _resMan(resMan), _audioRate(
_syncResource(NULL), _syncOffset(0), _audioCdStart(0) {
_mixer = g_system->getMixer();
+ _wPlayFlag = false;
}
AudioPlayer::~AudioPlayer() {
@@ -63,11 +65,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() {
@@ -85,6 +106,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
}
@@ -160,17 +183,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;
}
@@ -238,9 +272,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);
@@ -270,7 +306,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);
}
@@ -286,6 +322,18 @@ 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
@@ -317,13 +365,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/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..58803db260 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)
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..cc09ba79f0 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,76 @@ 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];
+ assert(realChannel != -1);
+
+ 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 +471,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) {
+ _signalSet = true;
+ _signalToSet = info.basic.param1;
+ }
} else {
- _loopTick = _position._play_tick;
+ _loopTick = _position._play_tick + info.delta;
}
}
break;
@@ -235,7 +539,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 +552,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 +608,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 +620,66 @@ 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;
-
- 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;
- }
- *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
+ int i, j;
-#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;
+ // Turn off all active notes
+ for (i = 0; i < 128; ++i) {
+ for (j = 0; j < 16; ++j) {
+ if ((_active_notes[i] & (1 << j)) && (_channelRemap[j] != -1)){
+ sendToDriver(0x80 | j, i, 0);
}
- if (command != global_prev)
- *outData++ = command; // out command
- *outData++ = par1;// pout par1
- if (nMidiParams[(command >> 4) - 8] == 2)
- *outData++ = *channel->data++; // out par2
- channel->prev = command;
- global_prev = command;
- }// switch(command)
- }// while (curr)
-
- // Insert stop event
- *outData++ = 0; // Delta
- *outData++ = 0xFF; // Meta event
- *outData++ = 0x2F; // End of track (EOT)
- *outData++ = 0x00;
- *outData++ = 0x00;
-
- for (int channelNr = 0; channelNr < _track->channelCount; channelNr++)
- _track->channels[channelNr].data = dataPtr[channelNr];
-
- delete[] dataPtr;
- return _mixedData;
-}
-
-// This is used for SCI0 sound-data. SCI0 only has one stream that may
-// contain several channels and according to output device we remove
-// certain channels from that data.
-byte *MidiParser_SCI::midiFilterChannels(int channelMask) {
- SoundResource::Channel *channel = &_track->channels[0];
- byte *channelData = channel->data;
- byte *channelDataEnd = channel->data + channel->size;
- byte *outData = new byte[channel->size + 5];
- byte curChannel = 15, curByte, curDelta;
- byte command = 0, lastCommand = 0;
- int delta = 0;
- int midiParamCount = 0;
-
- _mixedData = outData;
-
- while (channelData < channelDataEnd) {
- curDelta = *channelData++;
- if (curDelta == 0xF8) {
- delta += 240;
- continue;
}
- delta += curDelta;
- curByte = *channelData++;
+ }
- switch (curByte) {
- case 0xF0: // sysEx
- case kEndOfTrack: // end of channel
- command = curByte;
- curChannel = 15;
- break;
- default:
- if (curByte & 0x80) {
- command = curByte;
- curChannel = command & 0x0F;
- midiParamCount = nMidiParams[(command >> 4) - 8];
- }
+ // Turn off all hanging notes
+ for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) {
+ byte midiChannel = _hanging_notes[i].channel;
+ if ((_hanging_notes[i].time_left) && (_channelRemap[midiChannel] != -1)) {
+ sendToDriver(0x80 | midiChannel, _hanging_notes[i].note, 0);
+ _hanging_notes[i].time_left = 0;
}
- if ((1 << curChannel) & channelMask) {
- if (command != kEndOfTrack) {
- debugC(2, kDebugLevelSound, "\nDELTA ");
- // Write delta
- while (delta > 240) {
- *outData++ = 0xF8;
- debugC(2, kDebugLevelSound, "F8 ");
- delta -= 240;
- }
- *outData++ = (byte)delta;
- debugC(2, kDebugLevelSound, "%02X ", delta);
- delta = 0;
- }
- // Write command
- switch (command) {
- case 0xF0: // sysEx
- *outData++ = command;
- debugC(2, kDebugLevelSound, "%02X ", command);
- do {
- curByte = *channelData++;
- *outData++ = curByte; // out
- } while (curByte != 0xF7);
- lastCommand = command;
- break;
+ }
+ _hanging_notes_count = 0;
- case kEndOfTrack: // end of channel
- break;
+ // To be sure, send an "All Note Off" event (but not all MIDI devices
+ // support this...).
- default: // MIDI command
- if (lastCommand != command) {
- *outData++ = command;
- debugC(2, kDebugLevelSound, "%02X ", command);
- lastCommand = command;
- }
- if (midiParamCount > 0) {
- if (curByte & 0x80) {
- debugC(2, kDebugLevelSound, "%02X ", *channelData);
- *outData++ = *channelData++;
- } else {
- debugC(2, kDebugLevelSound, "%02X ", curByte);
- *outData++ = curByte;
- }
- }
- if (midiParamCount > 1) {
- debugC(2, kDebugLevelSound, "%02X ", *channelData);
- *outData++ = *channelData++;
- }
- }
- } else {
- if (curByte & 0x80) {
- channelData += midiParamCount;
- } else {
- channelData += midiParamCount - 1;
- }
- }
+ for (i = 0; i < 16; ++i) {
+ if (_channelRemap[i] != -1)
+ sendToDriver(0xB0 | i, 0x7b, 0); // All notes off
}
- // Insert stop event
- *outData++ = 0; // Delta
- *outData++ = 0xFF; // Meta event
- *outData++ = 0x2F; // End of track (EOT)
- *outData++ = 0x00;
- *outData++ = 0x00;
-
- return _mixedData;
+ memset(_active_notes, 0, sizeof(_active_notes));
}
void MidiParser_SCI::setVolume(byte volume) {
- // FIXME: This receives values > 127... throw a warning for now and clip the variable
- if (volume > MUSIC_VOLUME_MAX) {
- warning("attempted to set an invalid volume(%d)", volume);
- volume = MUSIC_VOLUME_MAX; // reset
- }
-
assert(volume <= MUSIC_VOLUME_MAX);
- if (_volume != volume) {
- _volume = volume;
-
- switch (_soundVersion) {
- case SCI_VERSION_0_EARLY:
- case SCI_VERSION_0_LATE: {
- int16 globalVolume = _volume * 15 / 127;
- ((MidiPlayer *)_driver)->setVolume(globalVolume);
- break;
- }
+ _volume = volume;
+
+ switch (_soundVersion) {
+ case SCI_VERSION_0_EARLY:
+ case SCI_VERSION_0_LATE: {
+ // SCI0 adlib driver doesn't support channel volumes, so we need to go this way
+ // TODO: this should take the actual master volume into account
+ int16 globalVolume = _volume * 15 / 127;
+ ((MidiPlayer *)_driver)->setVolume(globalVolume);
+ break;
+ }
- case SCI_VERSION_1_EARLY:
- case SCI_VERSION_1_LATE:
- // sending volume change to all active channels
- for (int i = 0; i < _track->channelCount; i++)
- if (_track->channels[i].number <= 0xF)
- _driver->send(0xB0 + _track->channels[i].number, 7, _volume);
- break;
+ case SCI_VERSION_1_EARLY:
+ case SCI_VERSION_1_LATE:
+ // 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..55a7e1fdc4 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,30 @@ 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.
+ // 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.
Common::Platform platform = g_sci->getPlatform();
-
- 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:
+ uint32 dev = MidiDriver::detectDevice(
+ (getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh ||
+ (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA))
+ ? (MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM)
+ : (MDT_PCSPK | MDT_ADLIB | MDT_MIDI));
+
+ 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);
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 +104,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 +166,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 +197,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 +229,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 +265,53 @@ 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;
+ }
+ }
+ error("no free channels");
+}
+
+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 +339,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 +362,54 @@ 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();
+ }
}
void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) {
@@ -353,7 +418,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 +435,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 +475,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 +521,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);
@@ -567,14 +655,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..943a5bd2a8 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
@@ -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..51832af09f 100644
--- a/engines/sci/sound/soundcmd.cpp
+++ b/engines/sci/sound/soundcmd.cpp
@@ -23,17 +23,12 @@
*
*/
-#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 {
@@ -41,258 +36,29 @@ 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) {
+ 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 +73,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): number %d, loop %d, prio %d, vol %d", 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 +102,28 @@ 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) {
+ 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 +141,31 @@ 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): number %d, loop %d, prio %d, vol %d", resourceId,
+ musicSlot->loop, musicSlot->priority, musicSlot->volume);
+ _music->soundPlay(musicSlot);
}
-void SoundCommandParser::cmdDummy(reg_t obj, int16 value) {
+reg_t SoundCommandParser::kDoSoundDummy(int argc, reg_t *argv, reg_t acc) {
warning("cmdDummy invoked"); // not supposed to occur
+ 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::kDoSoundDispose(int argc, reg_t *argv, reg_t acc) {
+ processDisposeSound(argv[0]);
+ 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
+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 +173,17 @@ 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) {
+ 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 +193,156 @@ 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);
- else
- changeSoundStatus(obj, value ? SOUND_STATUS_SUSPENDED : SOUND_STATUS_PLAYING);
-#else
+reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) {
+ 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
- // Pausing/Resuming the whole playlist was introduced
- // in the SCI1 late sound scheme
- if (_soundVersion <= SCI_VERSION_1_EARLY)
- return;
-
_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;
+ warning("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
+reg_t SoundCommandParser::kDoSoundResume(int argc, reg_t *argv, reg_t acc) {
+ // this doesn't seem to do what we think it's doing
+ // it's called with no arguments at all (just restore a game in qfg1)
+ return acc;
+ reg_t obj = argv[0];
-#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;
+ warning("kDoSound(resume):: Slot not found (%04x:%04x)", PRINT_REG(obj));
+ return acc;
}
writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying);
_music->soundResume(musicSlot);
-#endif
+ return acc;
}
-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
+reg_t SoundCommandParser::kDoSoundMute(int argc, reg_t *argv, reg_t acc) {
+ if (argc > 0)
+ _music->soundSetSoundOn(argv[0].toUint16());
+ return make_reg(0, _music->soundGetSoundOn());
}
-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): fading requested, but sound is currently not playing");
+ 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);
+ musicSlot->fadeStep = volume > argv[1].toUint16() ? -argv[3].toUint16() : argv[3].toUint16();
+ 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): to %d, step %d, ticker %d", 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];
-#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 +352,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;
}
@@ -828,7 +380,7 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) {
musicSlot->sampleLoopCounter = currentLoopCounter;
}
if ((!_music->soundIsActive(musicSlot)) && (musicSlot->status != kSoundPaused)) {
- processStopSound(obj, 0, true);
+ processStopSound(obj, true);
} else {
_music->updateAudioStreamTicker(musicSlot);
}
@@ -841,7 +393,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 +402,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 +418,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 +436,58 @@ 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;
+
+ uint16 controller = argv[3].toUint16();
+ uint16 param = argv[4].toUint16();
+
+ 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) {
+ _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];
+
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) {
Common::StackLock(_music->_mutex);
const MusicList::iterator end = _music->getPlayListEnd();
@@ -931,32 +495,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 +528,17 @@ 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();
-#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;
+ warning("kDoSound(setPriority): Slot not found (%04x:%04x)", PRINT_REG(obj));
+ return acc;
}
if (value == -1) {
@@ -987,7 +547,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 +558,26 @@ 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();
-#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 +586,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 +625,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..a8bc1eb280 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,43 @@ 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 kDoSoundDummy(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 kDoSoundResume(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 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/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/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/saveload.cpp b/engines/scumm/saveload.cpp
index 1375281aaf..1d064cdf6a 100644
--- a/engines/scumm/saveload.cpp
+++ b/engines/scumm/saveload.cpp
@@ -576,6 +576,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;
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 2d83622f05..86ec8c4748 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");
}
@@ -1735,11 +1735,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 +1749,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 +1769,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) {
@@ -2081,6 +2081,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 98fa3d0e4a..840f8fc779 100644
--- a/engines/scumm/sound.cpp
+++ b/engines/scumm/sound.cpp
@@ -1788,7 +1788,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..62fdf48440 100644
--- a/engines/scumm/string.cpp
+++ b/engines/scumm/string.cpp
@@ -1351,6 +1351,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..45b3cab947 100644
--- a/engines/sky/sky.cpp
+++ b/engines/sky/sky.cpp
@@ -259,16 +259,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/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/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/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/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/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 4335b51818..3a4191227a 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -855,11 +855,11 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc)
if (cd_num >= 0)
_system->getAudioCDManager()->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);
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/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/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/qt_decoder.cpp b/graphics/video/qt_decoder.cpp
index 49d2b0aed9..a95243ba6a 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() {
@@ -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/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..ff747c6e92 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"
@@ -48,7 +50,7 @@ enum {
// Constructor
GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled),
- _stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0) {
+ _stateIsSaved(false), _cursorAnimateCounter(0), _cursorAnimateTimer(0) {
_theme = 0;
_useStdCursor = false;
@@ -74,10 +76,13 @@ GuiManager::GuiManager() : _redrawStatus(kRedrawDisabled),
error("Failed to load any GUI theme, aborting");
}
}
+
+ _tooltip = new Tooltip(this);
}
GuiManager::~GuiManager() {
delete _theme;
+ delete _tooltip;
}
#ifdef ENABLE_KEYMAPPER
@@ -94,27 +99,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;
@@ -218,6 +224,13 @@ Dialog *GuiManager::getTopDialog() const {
return _dialogStack.top();
}
+static void tooltipCallback(void *ref) {
+ GuiManager *guiManager = (GuiManager *)ref;
+
+ guiManager->getTooltip()->setVisible(true);
+ g_system->getTimerManager()->removeTimerProc(&tooltipCallback);
+}
+
void GuiManager::runLoop() {
Dialog *activeDialog = getTopDialog();
bool didSaveState = false;
@@ -276,6 +289,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 +313,21 @@ 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);
+ _tooltip->setMouseXY(mouse.x, mouse.y);
+ 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 +344,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 +367,13 @@ void GuiManager::runLoop() {
}
}
+ if (eventTookplace) {
+ _tooltip->setVisible(false);
+
+ _system->getTimerManager()->removeTimerProc(&tooltipCallback);
+ _system->getTimerManager()->installTimerProc(&tooltipCallback, 2*1000000, this);
+ }
+
// Delay for a moment
_system->delayMillis(10);
}
diff --git a/gui/GuiManager.h b/gui/GuiManager.h
index 892d1aa3ac..2a187a92f9 100644
--- a/gui/GuiManager.h
+++ b/gui/GuiManager.h
@@ -60,6 +60,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 +72,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 +92,9 @@ public:
* @return true if the a screen change indeed occurred, false otherwise
*/
bool checkScreenChange();
+
+ Tooltip *getTooltip() { return _tooltip; }
+
protected:
enum RedrawStatus {
kRedrawDisabled = 0,
@@ -114,9 +118,11 @@ protected:
bool _useStdCursor;
+ Tooltip *_tooltip;
+
// 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;
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..e08bc09b0b 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;
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..30bacbb617 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"
@@ -189,6 +190,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 +334,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
};
@@ -392,17 +397,12 @@ bool ThemeEngine::init() {
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()) {
_themeArchive = new Common::FSDirectory(node);
}
@@ -563,10 +563,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 +891,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;
@@ -1039,7 +1072,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 +1123,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 +1165,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
@@ -1408,6 +1497,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
@@ -1441,7 +1558,6 @@ bool ThemeEngine::themeConfigUsable(const Common::FSNode &node, Common::String &
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 +1570,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())
@@ -1550,7 +1665,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 +1691,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..f0d4e2585d 100644
--- a/gui/ThemeEngine.h
+++ b/gui/ThemeEngine.h
@@ -82,6 +82,10 @@ enum DrawData {
kDDCheckboxDisabled,
kDDCheckboxSelected,
+ kDDRadiobuttonDefault,
+ kDDRadiobuttonDisabled,
+ kDDRadiobuttonSelected,
+
kDDTabActive,
kDDTabInactive,
kDDTabBackground,
@@ -108,6 +112,7 @@ enum TextData {
kTextDataDefault = 0,
kTextDataButton,
kTextDataNormalFont,
+ kTextDataTooltip,
kTextDataMAX
};
@@ -173,7 +178,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 +197,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 +261,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 +297,8 @@ public:
TextData fontStyleToData(FontStyle font) const {
if (font == kFontStyleNormal)
return kTextDataNormalFont;
+ if (font == kFontStyleTooltip)
+ return kTextDataTooltip;
return kTextDataDefault;
}
@@ -312,6 +331,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 +351,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);
@@ -517,6 +539,7 @@ protected:
const Graphics::Font *loadFont(const Common::String &filename);
const Graphics::Font *loadFontFromArchive(const Common::String &filename);
Common::String genCacheFilename(const char *filename);
+ Common::String genLocalizedFontFilename(const char *filename);
/**
* Actual Dirty Screen handling function.
diff --git a/gui/ThemeParser.cpp b/gui/ThemeParser.cpp
index e22d440bd9..4cabf6ad2e 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" }
};
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..a2aa56f5b3 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;
}
diff --git a/gui/credits.h b/gui/credits.h
index 0df894a642..ae658e1196 100644
--- a/gui/credits.h
+++ b/gui/credits.h
@@ -363,6 +363,29 @@ 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""Websites (design)",
"C0""Dob\363 Bal\341zs",
"C2""Website design",
@@ -479,7 +502,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/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..1daf9ffd50 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"
@@ -87,8 +88,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:
@@ -166,30 +167,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) {
@@ -199,18 +201,18 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
//
// 3) 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
//
- 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.");
@@ -218,18 +220,18 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
//
// 5) 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
//
- 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);
@@ -239,30 +241,30 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc)
//
// 2) The 'Path' tab
//
- tab->addTab("Paths");
+ 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 +272,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;
@@ -310,17 +312,16 @@ void EditGameDialog::open() {
// 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 +350,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();
@@ -387,14 +388,14 @@ void EditGameDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat
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 +407,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 +425,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 +437,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 +456,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 +497,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 +545,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 +620,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 +657,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 +705,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 +717,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 +731,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 +807,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 +870,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 +986,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 +1034,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/options.cpp b/gui/options.cpp
index 212e90f9f0..856eb668fa 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;
@@ -104,6 +100,8 @@ void OptionsDialog::init() {
_aspectCheckbox = 0;
_enableAudioSettings = false;
_midiPopUp = 0;
+ _mt32DevicePopUp = 0;
+ _gmDevicePopUp = 0;
_oplPopUp = 0;
_outputRatePopUp = 0;
_enableMIDISettings = false;
@@ -122,15 +120,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 +144,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,10 +194,25 @@ 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 (!loadMusicDeviceSetting(_mt32DevicePopUp, "mt32_device")) {
+ if (_domain.equals(Common::ConfigManager::kApplicationDomain)) {
+ if (!loadMusicDeviceSetting(_mt32DevicePopUp, Common::String(), MT_MT32))
+ _mt32DevicePopUp->setSelected(0);
+ } else {
+ _mt32DevicePopUp->setSelected(0);
+ }
+ }
+
+ 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);
+ }
}
if (_oplPopUp) {
@@ -222,7 +242,7 @@ void OptionsDialog::open() {
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);
@@ -263,11 +283,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,15 +352,13 @@ 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");
+ saveMusicDeviceSetting(_mt32DevicePopUp, "mt32_device");
+ saveMusicDeviceSetting(_gmDevicePopUp, "gm_device");
} else {
ConfMan.removeKey("music_driver", _domain);
+ ConfMan.removeKey("mt32_device", _domain);
+ ConfMan.removeKey("gm_device", _domain);
}
}
@@ -378,7 +397,7 @@ void OptionsDialog::close() {
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);
@@ -392,21 +411,21 @@ void OptionsDialog::close() {
}
// 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 +478,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 +511,24 @@ void OptionsDialog::setGraphicSettingsState(bool enabled) {
void OptionsDialog::setAudioSettingsState(bool enabled) {
_enableAudioSettings = enabled;
-
_midiPopUpDesc->setEnabled(enabled);
_midiPopUp->setEnabled(enabled);
- _oplPopUpDesc->setEnabled(enabled);
- _oplPopUp->setEnabled(enabled);
+ _mt32DevicePopUpDesc->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
+ _mt32DevicePopUp->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
+ _gmDevicePopUpDesc->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
+ _gmDevicePopUp->setEnabled(_domain.equals(Common::ConfigManager::kApplicationDomain) ? enabled : false);
+
+ 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);
}
@@ -522,7 +542,7 @@ void OptionsDialog::setMIDISettingsState(bool 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);
@@ -575,7 +595,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,64 +611,90 @@ 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"));
+
+ _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");
+ _gmDevicePopUpDesc = new StaticTextWidget(boss, prefix + "auPrefGmPopupDesc", _("GM Device:"), _("Specifies default sound device for General MIDI output"));
+ _gmDevicePopUp = new PopUpWidget(boss, prefix + "auPrefGmPopup");
// 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) {
+ 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 & (MidiDriver::musicType2GUIO(d->getMusicType())) // flag is present
+ || d->getMusicDriverId() == "auto" || d->getMusicDriverId() == "null") // always add default and null device
+ _midiPopUp->appendEntry(d->getCompleteName(), d->getHandle());
+
+ if (d->getMusicType() >= MT_GM || d->getMusicDriverId() == "auto") {
+ _mt32DevicePopUp->appendEntry(d->getCompleteName(), d->getHandle());
+ if (d->getMusicType() != MT_MT32)
+ _gmDevicePopUp->appendEntry(d->getCompleteName(), d->getHandle());
+ }
+ }
+ }
+
+ if (!_domain.equals(Common::ConfigManager::kApplicationDomain)) {
+ _mt32DevicePopUpDesc->setEnabled(false);
+ _mt32DevicePopUp->setEnabled(false);
+ _gmDevicePopUpDesc->setEnabled(false);
+ _gmDevicePopUp->setEnabled(false);
}
// 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;
@@ -656,22 +702,22 @@ void OptionsDialog::addAudioControls(GuiObject *boss, const Common::String &pref
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);
+ _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);
// Multi midi setting
- _multiMidiCheckbox = new CheckboxWidget(boss, prefix + "mcMixedCheckbox", "Mixed AdLib/MIDI mode", 0, 0);
+ _multiMidiCheckbox = new CheckboxWidget(boss, prefix + "mcMixedCheckbox", _("Mixed AdLib/MIDI mode"), _("Use both MIDI and AdLib sound generation"));
// Native mt32 setting
- _mt32Checkbox = new CheckboxWidget(boss, prefix + "mcMt32Checkbox", "True Roland MT-32 (disable GM emulation)", 0, 0);
+ _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", 0, 0);
+ _enableGSCheckbox = new CheckboxWidget(boss, prefix + "mcGSCheckbox", _("Enable Roland GS Mode"), _("Turns off General MIDI mapping for games with Roland MT-32 soundtrack"));
// 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");
@@ -683,12 +729,25 @@ void OptionsDialog::addMIDIControls(GuiObject *boss, const Common::String &prefi
// 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 +758,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 +785,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 +864,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 +882,95 @@ GlobalOptionsDialog::GlobalOptionsDialog()
//
// 3) The MIDI tab
//
- tab->addTab("MIDI");
+ tab->addTab(_("MIDI"));
addMIDIControls(tab, "GlobalOptions_MIDI.");
//
// 4) The miscellaneous 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");
+ 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.getSupportedLanguages();
+ 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 +993,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 +1013,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 +1037,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 +1070,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 +1099,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 +1115,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 +1125,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 +1136,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 +1147,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..235cb24462 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"
@@ -78,6 +79,9 @@ protected:
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,6 +108,13 @@ private:
StaticTextWidget *_outputRatePopUpDesc;
PopUpWidget *_outputRatePopUp;
+ StaticTextWidget *_mt32DevicePopUpDesc;
+ PopUpWidget *_mt32DevicePopUp;
+ StaticTextWidget *_gmDevicePopUpDesc;
+ PopUpWidget *_gmDevicePopUp;
+
+
+
//
// MIDI controls
//
@@ -121,8 +132,10 @@ private:
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 +166,7 @@ protected:
// Game GUI options
//
uint32 _guioptions;
+ Common::String _guioptionsString;
};
@@ -184,6 +198,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..086fecc123 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'> "
"<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,0' "
"/> "
"<widget name='TabWidget.NavButton' "
-"size='15,18' "
+"size='32,18' "
"padding='0,3,4,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,23 @@
"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='auPrefMt32PopupDesc' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='auPrefMt32Popup' "
+"type='PopUp' "
+"/> "
+"</layout> "
+"<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='6' center='true'> "
"<widget name='auOPLPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -548,7 +213,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 +221,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 +249,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 +261,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 +272,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 +283,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 +293,7 @@
"</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='16' center='true'> "
"<widget name='mcFontButton' "
"type='Button' "
"/> "
@@ -645,7 +314,7 @@
"<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' "
"/> "
@@ -661,7 +330,7 @@
"</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 +338,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 +346,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 +366,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 +374,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 +433,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 +448,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 +456,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,7 +464,7 @@
"</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' "
"/> "
@@ -789,7 +472,7 @@
"</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 +480,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 +525,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 +534,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 +542,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 +553,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 +612,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 +623,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 +634,35 @@
"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'> "
+"<space size='4' /> "
+"<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='4' /> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='6' center='true'> "
"<widget name='subSubtitleSpeedDesc' "
"type='OptionsLabel' "
"/> "
@@ -973,8 +673,8 @@
"type='SmallLabel' "
"/> "
"</layout> "
-"<space size='60'/> "
-"<layout type='horizontal' padding='0,0,0,0' spacing='10'> "
+"<space size='20'/> "
+"<layout type='horizontal' padding='0,0,0,0' spacing='4'> "
"<widget name='Keys' "
"type='Button' "
"/> "
@@ -989,23 +689,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 +707,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 +731,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 +755,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 +776,482 @@
"</layout> "
"</dialog> "
"</layout_info> "
-"<layout_info resolution='320xY,256x240,Xx272'> "
+"<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='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> "
+"<layout_info resolution='-320xY,-256x240,-Xx272'> "
"<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 +1263,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 +1301,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 +1339,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 +1353,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 +1369,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 +1377,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 +1395,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 +1403,23 @@
"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='auPrefMt32PopupDesc' "
+"type='OptionsLabel' "
+"/> "
+"<widget name='auPrefMt32Popup' "
+"type='PopUp' "
+"/> "
+"</layout> "
+"<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='auOPLPopupDesc' "
"type='OptionsLabel' "
"/> "
@@ -1273,7 +1427,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 +1435,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 +1463,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 +1476,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 +1487,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 +1498,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 +1508,7 @@
"</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='mcFontButton' "
"type='Button' "
"/> "
@@ -1369,7 +1529,7 @@
"<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' "
"/> "
@@ -1385,7 +1545,7 @@
"</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 +1553,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 +1561,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 +1581,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 +1589,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 +1642,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 +1657,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 +1665,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,7 +1673,7 @@
"</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' "
"/> "
@@ -1517,7 +1681,7 @@
"</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 +1689,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 +1725,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 +1734,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 +1742,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 +1753,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 +1814,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 +1825,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 +1836,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 +1873,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 +1889,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 +1915,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 +1939,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 +1963,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' "
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..b5866337ad 100644
--- a/gui/themes/scummclassic.zip
+++ b/gui/themes/scummclassic.zip
Binary files differ
diff --git a/gui/themes/scummclassic/classic_gfx.stx b/gui/themes/scummclassic/classic_gfx.stx
index cc6d7d471f..8c03aa932c 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'
@@ -418,9 +433,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..80bc4bf41e 100644
--- a/gui/themes/scummclassic/classic_layout.stx
+++ b/gui/themes/scummclassic/classic_layout.stx
@@ -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'
@@ -222,6 +232,22 @@
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
+ <widget name = 'auPrefMt32PopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefMt32Popup'
+ type = 'PopUp'
+ />
+ </layout>
+ <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 = 'auOPLPopupDesc'
type = 'OptionsLabel'
/>
@@ -241,9 +267,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'>
@@ -406,6 +437,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'
/>
@@ -653,9 +692,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..64ac6e200a 100644
--- a/gui/themes/scummclassic/classic_layout_lowres.stx
+++ b/gui/themes/scummclassic/classic_layout_lowres.stx
@@ -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,6 +89,9 @@
size = '45, 16'
padding = '0, 0, 2, 0'
/>
+ <widget name = 'TabWidget.Body'
+ padding = '0, 0, 0, 0'
+ />
<widget name = 'TabWidget.NavButton'
size = '32, 18'
padding = '0, 3, 4, 0'
@@ -89,11 +99,11 @@
</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'
/>
@@ -220,6 +230,22 @@
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <widget name = 'auPrefMt32PopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefMt32Popup'
+ type = 'PopUp'
+ />
+ </layout>
+ <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 = '6' center = 'true'>
<widget name = 'auOPLPopupDesc'
type = 'OptionsLabel'
/>
@@ -235,13 +261,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'>
@@ -407,6 +438,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'
/>
@@ -655,15 +696,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 = '1' center = 'true'>
<widget name = 'subToggleDesc'
type = 'OptionsLabel'
/>
- <widget name = 'subToggleButton'
- width = '128'
- height = 'Globals.Slider.Height'
- />
+ <layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <widget name = 'subToggleSpeechOnly'
+ type = 'Radiobutton'
+ width = '90'
+ />
+ <widget name = 'subToggleSubOnly'
+ type = 'Radiobutton'
+ width = '90'
+ />
+ <widget name = 'subToggleSubBoth'
+ type = 'Radiobutton'
+ width = '90'
+ />
+ </layout>
</layout>
+ <space size = '4' />
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
<widget name = 'subSubtitleSpeedDesc'
type = 'OptionsLabel'
diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip
index b3dc16b67e..aba0c944c3 100644
--- a/gui/themes/scummmodern.zip
+++ b/gui/themes/scummmodern.zip
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..ad41475a96 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'
@@ -595,6 +612,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 +664,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..796d4d9a94 100644
--- a/gui/themes/scummmodern/scummmodern_layout.stx
+++ b/gui/themes/scummmodern/scummmodern_layout.stx
@@ -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'>
@@ -235,6 +247,22 @@
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '10' center = 'true'>
+ <widget name = 'auPrefMt32PopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefMt32Popup'
+ type = 'PopUp'
+ />
+ </layout>
+ <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 = 'auOPLPopupDesc'
type = 'OptionsLabel'
/>
@@ -254,9 +282,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'>
@@ -419,6 +452,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'
/>
@@ -666,9 +707,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..8bb31e9f8a 100644
--- a/gui/themes/scummmodern/scummmodern_layout_lowres.stx
+++ b/gui/themes/scummmodern/scummmodern_layout_lowres.stx
@@ -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,6 +87,9 @@
size = '45, 16'
padding = '0, 0, 2, 0'
/>
+ <widget name = 'TabWidget.Body'
+ padding = '0, 0, 0, 0'
+ />
<widget name = 'TabWidget.NavButton'
size = '32, 18'
padding = '0, 3, 4, 0'
@@ -87,11 +97,11 @@
</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'
/>
@@ -218,6 +228,22 @@
/>
</layout>
<layout type = 'horizontal' padding = '0, 0, 0, 0' spacing = '6' center = 'true'>
+ <widget name = 'auPrefMt32PopupDesc'
+ type = 'OptionsLabel'
+ />
+ <widget name = 'auPrefMt32Popup'
+ type = 'PopUp'
+ />
+ </layout>
+ <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 = '6' center = 'true'>
<widget name = 'auOPLPopupDesc'
type = 'OptionsLabel'
/>
@@ -233,13 +259,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'>
@@ -389,6 +420,7 @@
<widget name = 'RendererPopupDesc'
width = '80'
height = 'Globals.Line.Height'
+ textalign = 'right'
/>
<widget name = 'RendererPopup'
type = 'PopUp'
@@ -398,11 +430,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'
/>
@@ -651,15 +694,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..14cb61006b 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,139 @@ 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 -
+
+Tooltip::Tooltip(GuiManager *guiManager) : GuiObject(0, 0, 0, 0) {
+ _guiManager = guiManager;
+
+ _visible = false;
+ _maxWidth = -1;
+ _storedState = 0;
+}
+
+void Tooltip::draw() {
+ int num = 0;
+ int h = g_gui.theme()->getFontHeight(ThemeEngine::kFontStyleTooltip) + 2;
+
+ // Make Rect bigger for compensating the shadow
+ _storedState = g_gui.theme()->storeState(Common::Rect(_x - 5, _y - 5, _x + _w + 5, _y + _h + 5));
+
+ g_gui.theme()->startBuffering();
+ g_gui.theme()->drawWidgetBackground(Common::Rect(_x, _y, _x + _w, _y + _h), 0, ThemeEngine::kWidgetBackgroundBorderSmall);
+
+ 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);
+ }
+ g_gui.theme()->finishBuffering();
+}
+
+void Tooltip::reflowLayout() {
+}
+
+void Tooltip::setMouseXY(int x, int y) {
+ _mouseX = x;
+ _mouseY = y;
+}
+
+void Tooltip::setVisible(bool state) {
+ if (state == _visible)
+ return;
+
+ if (state) {
+ if (!_guiManager->getTopDialog())
+ return;
+
+ Widget *wdg = _guiManager->getTopDialog()->findWidget(_mouseX, _mouseY);
+
+ if (!wdg)
+ return;
+
+ if (wdg->getTooltip()) {
+ _visible = state;
+
+ // Cache config values.
+ // NOTE: we cannot do it in the consturctor
+ 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>(_guiManager->getTopDialog()->_x + _mouseX + _xdelta, g_gui.getWidth() - _w - 3);
+ _y = MIN<int16>(_guiManager->getTopDialog()->_y + _mouseY + _ydelta, g_gui.getHeight() - _h - 3);
+
+ draw();
+ }
+ } else {
+ _visible = state;
+
+ g_gui.theme()->restoreState(_storedState);
+ delete _storedState;
+ }
+}
+
#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 +349,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 +380,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 +412,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 -
+
+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, uint32 cmd)
- : Widget(boss, x, y, w, h), CommandSender(boss),
+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 +561,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 +583,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 +601,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 +612,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..7b5fe9253f 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);
@@ -151,14 +159,39 @@ protected:
void handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { assert(_boss); _boss->handleCommand(sender, cmd, data); }
};
+class GuiManager;
+
+class Tooltip : public GuiObject {
+public:
+ Tooltip(GuiManager *guiManager);
+
+ bool isVisible() const { return _visible; }
+ void draw();
+ void reflowLayout();
+ void releaseFocus() {}
+ void setVisible(bool state);
+ void setMouseXY(int x, int y);
+
+protected:
+ Common::String _text;
+ GuiManager *_guiManager;
+ bool _visible;
+ int _mouseX, _mouseY;
+ int _maxWidth;
+ int _xdelta, _ydelta;
+
+ Common::StringArray _wrappedLines;
+ ThemeEngine::StoredState *_storedState;
+};
+
/* StaticTextWidget */
class StaticTextWidget : public Widget {
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 +209,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 +228,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 +243,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 +301,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 +333,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..7905fbdf16
--- /dev/null
+++ b/po/ca_ES.po
@@ -0,0 +1,1447 @@
+# 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-12 17:44+0200\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"
+"Language: Catalan\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\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:266 gui/massadd.cpp:95 gui/options.cpp:972
+#: 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:102 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "Tanca"
+
+#: gui/GuiManager.cpp:105
+msgid "Mouse click"
+msgstr "Clic del ratolí"
+
+#: gui/GuiManager.cpp:108 base/main.cpp:285
+msgid "Display keyboard"
+msgstr "Mostra el teclat"
+
+#: gui/GuiManager.cpp:111 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:267 gui/launcher.cpp:873
+#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973
+#: 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:170
+msgid "Game"
+msgstr "Joc"
+
+#: gui/launcher.cpp:173
+msgid "ID:"
+msgstr "Identificador:"
+
+#: gui/launcher.cpp:173 gui/launcher.cpp:174
+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:177
+msgid "Name:"
+msgstr "Nom:"
+
+#: gui/launcher.cpp:177 gui/launcher.cpp:178
+msgid "Full title of the game"
+msgstr "Títol complet del joc"
+
+#: gui/launcher.cpp:181
+msgid "Language:"
+msgstr "Idioma:"
+
+#: gui/launcher.cpp:181 gui/launcher.cpp:182
+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:183 gui/launcher.cpp:194 gui/options.cpp:80
+#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<per defecte>"
+
+#: gui/launcher.cpp:192
+msgid "Platform:"
+msgstr "Plataforma:"
+
+#: gui/launcher.cpp:192 gui/launcher.cpp:193
+msgid "Platform the game was originally designed for"
+msgstr "Plataforma per la que el joc es va dissenyar originalment"
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "Graphics"
+msgstr "Gràfics"
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "GFX"
+msgstr "GFX"
+
+#: gui/launcher.cpp:206
+msgid "Override global graphic settings"
+msgstr "Fer canvis sobre les opcions globals de gràfics"
+
+#: gui/launcher.cpp:213 gui/options.cpp:873
+msgid "Audio"
+msgstr "Àudio"
+
+#: gui/launcher.cpp:215
+msgid "Override global audio settings"
+msgstr "Fer canvis sobre les opcions globals d'àudio"
+
+#: gui/launcher.cpp:223 gui/options.cpp:877
+msgid "Volume"
+msgstr "Volum"
+
+#: gui/launcher.cpp:225
+msgid "Override global volume settings"
+msgstr "Fer canvis sobre les opcions globals de volum"
+
+#: gui/launcher.cpp:232 gui/options.cpp:885
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:234
+msgid "Override global MIDI settings"
+msgstr "Fer canvis sobre les opcions globals de MIDI"
+
+#: gui/launcher.cpp:244 gui/options.cpp:891
+msgid "Paths"
+msgstr "Camins"
+
+#: gui/launcher.cpp:250
+msgid "Game Path:"
+msgstr "Camí del Joc:"
+
+#: gui/launcher.cpp:254 gui/options.cpp:904
+msgid "Extra Path:"
+msgstr "Camí Extra:"
+
+#: gui/launcher.cpp:254 gui/launcher.cpp:255
+msgid "Specifies path to additional data used the game"
+msgstr "Especifica el camí de dades addicionals utilitzades pel joc"
+
+#: gui/launcher.cpp:258
+msgid "Save Path:"
+msgstr "Camí de les Partides:"
+
+#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898
+#: gui/options.cpp:899
+msgid "Specifies where your savegames are put"
+msgstr "Especifica on es desaran les partides"
+
+#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398
+#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486
+#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902
+#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996
+#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016
+#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050
+#: gui/options.cpp:1057 gui/options.cpp:1156
+msgid "None"
+msgstr "Cap"
+
+#: gui/launcher.cpp:280 gui/launcher.cpp:357
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "Per defecte"
+
+#: gui/launcher.cpp:391 gui/options.cpp:1150
+msgid "Select SoundFont"
+msgstr "Seleccioneu el fitxer SoundFont"
+
+#: gui/launcher.cpp:410 gui/launcher.cpp:548
+msgid "Select directory with game data"
+msgstr "Seleccioneu el directori amb les dades del joc"
+
+#: gui/launcher.cpp:428
+msgid "Select additional game directory"
+msgstr "Seleccioneu el directori addicional del joc"
+
+#: gui/launcher.cpp:440
+msgid "Select directory for saved games"
+msgstr "Seleccioneu el directori de les partides desades"
+
+#: gui/launcher.cpp:459
+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:500 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "~T~anca"
+
+#: gui/launcher.cpp:500
+msgid "Quit ScummVM"
+msgstr "Surt de ScummVM"
+
+#: gui/launcher.cpp:501
+msgid "A~b~out..."
+msgstr "~Q~uant a..."
+
+#: gui/launcher.cpp:501
+msgid "About ScummVM"
+msgstr "Quant a ScummVM"
+
+#: gui/launcher.cpp:502
+msgid "~O~ptions..."
+msgstr "~O~pcions..."
+
+#: gui/launcher.cpp:502
+msgid "Change global ScummVM options"
+msgstr "Canvia les opcions globals de ScummVM"
+
+#: gui/launcher.cpp:504
+msgid "~S~tart"
+msgstr "~I~nicia"
+
+#: gui/launcher.cpp:504
+msgid "Start selected game"
+msgstr "Iniciant el joc seleccionat"
+
+#: gui/launcher.cpp:507
+msgid "~L~oad..."
+msgstr "~C~arrega..."
+
+#: gui/launcher.cpp:507
+msgid "Load savegame for selected game"
+msgstr "Carrega una partida pel joc seleccionat"
+
+#: gui/launcher.cpp:511
+msgid "~A~dd Game..."
+msgstr "~A~fegeix Joc..."
+
+#: gui/launcher.cpp:511
+msgid "Hold Shift for Mass Add"
+msgstr "Mantingueu premut Shift per a l'Addició Massiva"
+
+#: gui/launcher.cpp:513
+msgid "~E~dit Game..."
+msgstr "~E~dita Joc..."
+
+#: gui/launcher.cpp:513
+msgid "Change game options"
+msgstr "Canvia les opcions del joc"
+
+#: gui/launcher.cpp:515
+msgid "~R~emove Game"
+msgstr "~S~uprimeix Joc"
+
+#: gui/launcher.cpp:515
+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:522
+msgid "Search in game list"
+msgstr "Cerca a la llista de jocs"
+
+#: gui/launcher.cpp:526 gui/launcher.cpp:1037
+msgid "Search:"
+msgstr "Cerca:"
+
+#: gui/launcher.cpp:529 gui/options.cpp:707
+msgid "Clear value"
+msgstr "Neteja el valor"
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "Carrega partida:"
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "Carrega"
+
+#: gui/launcher.cpp:660
+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:661 gui/launcher.cpp:810
+#: 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:661 gui/launcher.cpp:810
+#: 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:708
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM no ha pogut obrir el directori especificat!"
+
+#: gui/launcher.cpp:720
+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:734
+msgid "Pick the game:"
+msgstr "Seleccioneu el joc:"
+
+#: gui/launcher.cpp:810
+msgid "Do you really want to remove this game configuration?"
+msgstr "Realment voleu suprimir la configuració d'aquest joc?"
+
+#: gui/launcher.cpp:873
+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:877
+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:989
+msgid "Mass Add..."
+msgstr "Addició Massiva..."
+
+#: gui/launcher.cpp:990
+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:614
+msgid "Graphics mode:"
+msgstr "Mode gràfic:"
+
+#: gui/options.cpp:625
+msgid "Render mode:"
+msgstr "Mode de pintat:"
+
+#: gui/options.cpp:625 gui/options.cpp:626
+msgid "Special dithering modes supported by some games"
+msgstr "Modes de dispersió especials suportats per alguns jocs"
+
+#: gui/options.cpp:635
+msgid "Fullscreen mode"
+msgstr "Mode pantalla completa"
+
+#: gui/options.cpp:638
+msgid "Aspect ratio correction"
+msgstr "Correcció del rati d'aspecte"
+
+#: gui/options.cpp:638
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "Corregeix la relació d'aspecte per jocs de 320x200"
+
+#: gui/options.cpp:645
+msgid "Preferred Device:"
+msgstr "Dispositiu Preferit:"
+
+#: gui/options.cpp:645
+#, fuzzy
+msgid "Music Device:"
+msgstr "Dispositiu GM:"
+
+#: gui/options.cpp:645
+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:645 gui/options.cpp:646
+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:648
+#, fuzzy
+msgid "MT-32 Device:"
+msgstr "Dispositiu MT32:"
+
+#: gui/options.cpp:648
+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:650
+msgid "GM Device:"
+msgstr "Dispositiu GM:"
+
+#: gui/options.cpp:650
+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:682
+msgid "AdLib emulator:"
+msgstr "Emulador d'AdLib:"
+
+#: gui/options.cpp:682 gui/options.cpp:683
+msgid "AdLib is used for music in many games"
+msgstr "AdLib s'utilitza per la música de molts jocs"
+
+#: gui/options.cpp:693
+msgid "Output rate:"
+msgstr "Freqüència de sortida:"
+
+#: gui/options.cpp:693 gui/options.cpp:694
+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:705
+msgid "SoundFont:"
+msgstr "Fitxer SoundFont:"
+
+#: gui/options.cpp:705 gui/options.cpp:706
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr "Algunes targes de so, Fluidsynth i Timidity suporten SoundFont"
+
+#: gui/options.cpp:710
+msgid "Mixed AdLib/MIDI mode"
+msgstr "Mode combinat AdLib/MIDI"
+
+#: gui/options.cpp:710
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "Utilitza MIDI i la generació de so AdLib alhora"
+
+#: gui/options.cpp:713
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Roland MT-32 real (desactiva l'emulació GM)"
+
+#: gui/options.cpp:713
+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:716
+msgid "Enable Roland GS Mode"
+msgstr "Activa el Mode Roland GS"
+
+#: gui/options.cpp:716
+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:719
+msgid "MIDI gain:"
+msgstr "Guany MIDI:"
+
+#: gui/options.cpp:732
+msgid "Text and Speech:"
+msgstr "Text i Veus:"
+
+#: gui/options.cpp:737 gui/options.cpp:743
+msgid "Speech"
+msgstr "Veus"
+
+#: gui/options.cpp:738 gui/options.cpp:744
+msgid "Subtitles"
+msgstr "Subtítols"
+
+#: gui/options.cpp:739 gui/options.cpp:745
+msgid "Both"
+msgstr "Ambdós"
+
+#: gui/options.cpp:743
+msgid "Spch"
+msgstr "Veus"
+
+#: gui/options.cpp:744
+msgid "Subs"
+msgstr "Subt"
+
+#: gui/options.cpp:745
+msgid "Show subtitles and play speech"
+msgstr "Mostra els subtítols i reprodueix la veu"
+
+#: gui/options.cpp:749
+msgid "Subtitle speed:"
+msgstr "Velocitat dels subtítols:"
+
+#: gui/options.cpp:761
+msgid "Music volume:"
+msgstr "Volum de la música:"
+
+#: gui/options.cpp:768
+msgid "Mute All"
+msgstr "Silenciar tot"
+
+#: gui/options.cpp:771
+msgid "SFX volume:"
+msgstr "Volum dels efectes:"
+
+#: gui/options.cpp:771 gui/options.cpp:772
+msgid "Special sound effects volume"
+msgstr "Volum dels sons d'efectes especials"
+
+#: gui/options.cpp:778
+msgid "Speech volume:"
+msgstr "Volum de la veu:"
+
+#: gui/options.cpp:898
+msgid "Save Path: "
+msgstr "Camí de les Partides: "
+
+#: gui/options.cpp:901
+msgid "Theme Path:"
+msgstr "Camí dels Temes:"
+
+#: gui/options.cpp:904 gui/options.cpp:905
+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:908
+msgid "Plugins Path:"
+msgstr "Camí dels connectors:"
+
+#: gui/options.cpp:913
+msgid "Misc"
+msgstr "Misc"
+
+#: gui/options.cpp:915
+msgid "Theme:"
+msgstr "Tema:"
+
+#: gui/options.cpp:919
+msgid "GUI Renderer:"
+msgstr "Mode de pintat de la interfície d'usuari:"
+
+#: gui/options.cpp:925
+msgid "Autosave:"
+msgstr "Desat automàtic:"
+
+#: gui/options.cpp:933
+msgid "Keys"
+msgstr "Tecles"
+
+#: gui/options.cpp:940
+msgid "GUI Language:"
+msgstr "Idioma de la interfície d'usuari:"
+
+#: gui/options.cpp:940
+msgid "Language of ScummVM GUI"
+msgstr "Idioma de la interfície d'usuari de ScummVM"
+
+#: gui/options.cpp:945
+msgid "English"
+msgstr "Anglès"
+
+#: gui/options.cpp:1089
+msgid "You have to restart ScummVM to take the effect."
+msgstr "Heu de reiniciar ScummVM perquè tots els canvis tingui efecte."
+
+#: gui/options.cpp:1102
+msgid "Select directory for savegames"
+msgstr "Seleccioneu el directori de les partides desades"
+
+#: gui/options.cpp:1109
+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:1118
+msgid "Select directory for GUI themes"
+msgstr "Seleccioneu el directori dels temes de la Interfície d'Usuari"
+
+#: gui/options.cpp:1128
+msgid "Select directory for extra files"
+msgstr "Seleccioneu el directori dels fitxers extra"
+
+#: gui/options.cpp:1139
+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:337
+msgid "Disabled GFX"
+msgstr "GFX desactivats"
+
+#: gui/ThemeEngine.cpp:338
+msgid "Standard Renderer (16bpp)"
+msgstr "Pintat estàndard (16bpp)"
+
+#: gui/ThemeEngine.cpp:340
+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..4b3f493a03
--- /dev/null
+++ b/po/de_DE.po
@@ -0,0 +1,1442 @@
+# 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-12 17:44+0200\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"
+"Language: Deutsch\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\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:266 gui/massadd.cpp:95 gui/options.cpp:972
+#: 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:102 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "Schließen"
+
+#: gui/GuiManager.cpp:105
+msgid "Mouse click"
+msgstr "Mausklick"
+
+#: gui/GuiManager.cpp:108 base/main.cpp:285
+msgid "Display keyboard"
+msgstr "Tastatur anzeigen"
+
+#: gui/GuiManager.cpp:111 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:267 gui/launcher.cpp:873
+#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973
+#: 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:170
+msgid "Game"
+msgstr "Spiel"
+
+#: gui/launcher.cpp:173
+msgid "ID:"
+msgstr "Kennung:"
+
+#: gui/launcher.cpp:173 gui/launcher.cpp:174
+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:177
+msgid "Name:"
+msgstr "Name:"
+
+#: gui/launcher.cpp:177 gui/launcher.cpp:178
+msgid "Full title of the game"
+msgstr "Voller Name des Spiels"
+
+#: gui/launcher.cpp:181
+msgid "Language:"
+msgstr "Sprache:"
+
+#: gui/launcher.cpp:181 gui/launcher.cpp:182
+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:183 gui/launcher.cpp:194 gui/options.cpp:80
+#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<Standard>"
+
+#: gui/launcher.cpp:192
+msgid "Platform:"
+msgstr "Plattform:"
+
+#: gui/launcher.cpp:192 gui/launcher.cpp:193
+msgid "Platform the game was originally designed for"
+msgstr "Plattform, für die das Spiel ursprünglich erstellt wurde"
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "Graphics"
+msgstr "Grafik"
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "GFX"
+msgstr "GFX"
+
+#: gui/launcher.cpp:206
+msgid "Override global graphic settings"
+msgstr "Globale Grafikeinstellungen übergehen"
+
+#: gui/launcher.cpp:213 gui/options.cpp:873
+msgid "Audio"
+msgstr "Audio"
+
+#: gui/launcher.cpp:215
+msgid "Override global audio settings"
+msgstr "Globale Audioeinstellungen übergehen"
+
+#: gui/launcher.cpp:223 gui/options.cpp:877
+msgid "Volume"
+msgstr "Lautstärke"
+
+#: gui/launcher.cpp:225
+msgid "Override global volume settings"
+msgstr "Globale Lautstärke-Einstellungen übergehen"
+
+#: gui/launcher.cpp:232 gui/options.cpp:885
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:234
+msgid "Override global MIDI settings"
+msgstr "Globale MIDI-Einstellungen übergehen"
+
+#: gui/launcher.cpp:244 gui/options.cpp:891
+msgid "Paths"
+msgstr "Pfade"
+
+#: gui/launcher.cpp:250
+msgid "Game Path:"
+msgstr "Spielpfad:"
+
+#: gui/launcher.cpp:254 gui/options.cpp:904
+msgid "Extra Path:"
+msgstr "Extrapfad:"
+
+#: gui/launcher.cpp:254 gui/launcher.cpp:255
+msgid "Specifies path to additional data used the game"
+msgstr "Legt das Verzeichnis für zusätzliche Spieldateien fest."
+
+#: gui/launcher.cpp:258
+msgid "Save Path:"
+msgstr "Spielstände:"
+
+#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898
+#: gui/options.cpp:899
+msgid "Specifies where your savegames are put"
+msgstr "Legt fest, wo die Spielstände abgelegt werden."
+
+#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398
+#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486
+#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902
+#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996
+#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016
+#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050
+#: gui/options.cpp:1057 gui/options.cpp:1156
+msgid "None"
+msgstr "-"
+
+#: gui/launcher.cpp:280 gui/launcher.cpp:357
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "Standard"
+
+#: gui/launcher.cpp:391 gui/options.cpp:1150
+msgid "Select SoundFont"
+msgstr "SoundFont auswählen"
+
+#: gui/launcher.cpp:410 gui/launcher.cpp:548
+msgid "Select directory with game data"
+msgstr "Verzeichnis mit Spieldateien auswählen"
+
+#: gui/launcher.cpp:428
+msgid "Select additional game directory"
+msgstr "Verzeichnis mit zusätzlichen Dateien auswählen"
+
+#: gui/launcher.cpp:440
+msgid "Select directory for saved games"
+msgstr "Verzeichnis für Spielstände auswählen"
+
+#: gui/launcher.cpp:459
+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:500 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "~B~eenden"
+
+#: gui/launcher.cpp:500
+msgid "Quit ScummVM"
+msgstr "ScummVM beenden"
+
+#: gui/launcher.cpp:501
+msgid "A~b~out..."
+msgstr "Übe~r~"
+
+#: gui/launcher.cpp:501
+msgid "About ScummVM"
+msgstr "Über ScummVM"
+
+#: gui/launcher.cpp:502
+msgid "~O~ptions..."
+msgstr "~O~ptionen"
+
+#: gui/launcher.cpp:502
+msgid "Change global ScummVM options"
+msgstr "Globale ScummVM-Einstellungen bearbeiten"
+
+#: gui/launcher.cpp:504
+msgid "~S~tart"
+msgstr "~S~tarten"
+
+#: gui/launcher.cpp:504
+msgid "Start selected game"
+msgstr "Ausgewähltes Spiel starten"
+
+#: gui/launcher.cpp:507
+msgid "~L~oad..."
+msgstr "~L~aden..."
+
+#: gui/launcher.cpp:507
+msgid "Load savegame for selected game"
+msgstr "Spielstand für ausgewähltes Spiel laden"
+
+#: gui/launcher.cpp:511
+msgid "~A~dd Game..."
+msgstr "Spiel ~h~inzufügen"
+
+#: gui/launcher.cpp:511
+msgid "Hold Shift for Mass Add"
+msgstr ""
+"Umschalttaste (Shift) gedrückt halten, um Verzeichnisse nach Spielen zu "
+"durchsuchen"
+
+#: gui/launcher.cpp:513
+msgid "~E~dit Game..."
+msgstr "Spielo~p~tionen"
+
+#: gui/launcher.cpp:513
+msgid "Change game options"
+msgstr "Spieloptionen ändern"
+
+#: gui/launcher.cpp:515
+msgid "~R~emove Game"
+msgstr "Spiel ~e~ntfernen"
+
+#: gui/launcher.cpp:515
+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:522
+msgid "Search in game list"
+msgstr "In Spieleliste suchen"
+
+#: gui/launcher.cpp:526 gui/launcher.cpp:1037
+msgid "Search:"
+msgstr "Suchen:"
+
+#: gui/launcher.cpp:529 gui/options.cpp:707
+msgid "Clear value"
+msgstr "Wert löschen"
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "Spiel laden:"
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "Laden"
+
+#: gui/launcher.cpp:660
+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:661 gui/launcher.cpp:810
+#: 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:661 gui/launcher.cpp:810
+#: 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:708
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM kann das gewählte Verzeichnis nicht öffnen!"
+
+#: gui/launcher.cpp:720
+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:734
+msgid "Pick the game:"
+msgstr "Spiel auswählen:"
+
+#: gui/launcher.cpp:810
+msgid "Do you really want to remove this game configuration?"
+msgstr "Möchten Sie wirklich diese Spielkonfiguration entfernen?"
+
+#: gui/launcher.cpp:873
+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:877
+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:989
+msgid "Mass Add..."
+msgstr "Durchsuchen"
+
+#: gui/launcher.cpp:990
+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:614
+msgid "Graphics mode:"
+msgstr "Grafikmodus:"
+
+#: gui/options.cpp:625
+msgid "Render mode:"
+msgstr "Render-Modus:"
+
+#: gui/options.cpp:625 gui/options.cpp:626
+msgid "Special dithering modes supported by some games"
+msgstr ""
+"Spezielle Farbmischungsmethoden werden von manchen Spielen unterstützt."
+
+#: gui/options.cpp:635
+msgid "Fullscreen mode"
+msgstr "Vollbildmodus"
+
+#: gui/options.cpp:638
+msgid "Aspect ratio correction"
+msgstr "Seitenverhältnis korrigieren"
+
+#: gui/options.cpp:638
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "Seitenverhältnis für Spiele mit der Auflösung 320x200 korrigieren"
+
+#: gui/options.cpp:645
+msgid "Preferred Device:"
+msgstr "Standard-Gerät:"
+
+#: gui/options.cpp:645
+msgid "Music Device:"
+msgstr "Musikgerät:"
+
+#: gui/options.cpp:645
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr ""
+"Legt das bevorzugte Tonwiedergabe-Gerät oder den Soundkarten-Emulator fest."
+
+#: gui/options.cpp:645 gui/options.cpp:646
+msgid "Specifies output sound device or sound card emulator"
+msgstr "Legt das Musikwiedergabe-Gerät oder den Soundkarten-Emulator fest."
+
+#: gui/options.cpp:648
+#, fuzzy
+msgid "MT-32 Device:"
+msgstr "MT32-Gerät:"
+
+#: gui/options.cpp:648
+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:650
+msgid "GM Device:"
+msgstr "GM-Gerät:"
+
+#: gui/options.cpp:650
+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:682
+msgid "AdLib emulator:"
+msgstr "AdLib-Emulator"
+
+#: gui/options.cpp:682 gui/options.cpp:683
+msgid "AdLib is used for music in many games"
+msgstr "AdLib wird für die Musik in vielen Spielen verwendet."
+
+#: gui/options.cpp:693
+msgid "Output rate:"
+msgstr "Ausgabefrequenz:"
+
+#: gui/options.cpp:693 gui/options.cpp:694
+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:705
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:705 gui/options.cpp:706
+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:710
+msgid "Mixed AdLib/MIDI mode"
+msgstr "AdLib-/MIDI-Modus"
+
+#: gui/options.cpp:710
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "Benutzt MIDI und AdLib zur Sounderzeugung."
+
+#: gui/options.cpp:713
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Echte Roland-MT-32-Emulation (GM-Emulation deaktiviert)"
+
+#: gui/options.cpp:713
+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:716
+msgid "Enable Roland GS Mode"
+msgstr "Roland-GS-Modus"
+
+#: gui/options.cpp:716
+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:719
+msgid "MIDI gain:"
+msgstr "MIDI-Lautstärke:"
+
+#: gui/options.cpp:732
+msgid "Text and Speech:"
+msgstr "Text und Sprache:"
+
+#: gui/options.cpp:737 gui/options.cpp:743
+msgid "Speech"
+msgstr "Sprache"
+
+#: gui/options.cpp:738 gui/options.cpp:744
+msgid "Subtitles"
+msgstr "Untertitel"
+
+#: gui/options.cpp:739 gui/options.cpp:745
+msgid "Both"
+msgstr "Beides"
+
+#: gui/options.cpp:743
+msgid "Spch"
+msgstr "Spr."
+
+#: gui/options.cpp:744
+msgid "Subs"
+msgstr "Untert."
+
+#: gui/options.cpp:745
+msgid "Show subtitles and play speech"
+msgstr "Untertitel anzeigen und Sprachausgabe aktivieren"
+
+#: gui/options.cpp:749
+msgid "Subtitle speed:"
+msgstr "Untertitel-Tempo:"
+
+#: gui/options.cpp:761
+msgid "Music volume:"
+msgstr "Musiklautstärke:"
+
+#: gui/options.cpp:768
+msgid "Mute All"
+msgstr "Alles aus"
+
+#: gui/options.cpp:771
+msgid "SFX volume:"
+msgstr "Effektlautstärke:"
+
+#: gui/options.cpp:771 gui/options.cpp:772
+msgid "Special sound effects volume"
+msgstr "Lautstärke spezieller Soundeffekte"
+
+#: gui/options.cpp:778
+msgid "Speech volume:"
+msgstr "Sprachlautstärke:"
+
+#: gui/options.cpp:898
+msgid "Save Path: "
+msgstr "Spielstände: "
+
+#: gui/options.cpp:901
+msgid "Theme Path:"
+msgstr "Themenpfad:"
+
+#: gui/options.cpp:904 gui/options.cpp:905
+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:908
+msgid "Plugins Path:"
+msgstr "Plugin-Pfad:"
+
+#: gui/options.cpp:913
+msgid "Misc"
+msgstr "Sonstiges"
+
+#: gui/options.cpp:915
+msgid "Theme:"
+msgstr "Thema:"
+
+#: gui/options.cpp:919
+msgid "GUI Renderer:"
+msgstr "GUI-Renderer:"
+
+#: gui/options.cpp:925
+msgid "Autosave:"
+msgstr "Autom. Speichern:"
+
+#: gui/options.cpp:933
+msgid "Keys"
+msgstr "Tasten"
+
+#: gui/options.cpp:940
+msgid "GUI Language:"
+msgstr "GUI-Sprache:"
+
+#: gui/options.cpp:940
+msgid "Language of ScummVM GUI"
+msgstr "Sprache der ScummVM-Oberfläche"
+
+#: gui/options.cpp:945
+msgid "English"
+msgstr "English"
+
+#: gui/options.cpp:1089
+msgid "You have to restart ScummVM to take the effect."
+msgstr "Sie müssen ScummVM neustarten, um die Einstellungen zu übernehmen."
+
+#: gui/options.cpp:1102
+msgid "Select directory for savegames"
+msgstr "Verzeichnis für Spielstände auswählen"
+
+#: gui/options.cpp:1109
+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:1118
+msgid "Select directory for GUI themes"
+msgstr "Verzeichnis für Oberflächen-Themen"
+
+#: gui/options.cpp:1128
+msgid "Select directory for extra files"
+msgstr "Verzeichnis für zusätzliche Dateien auswählen"
+
+#: gui/options.cpp:1139
+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:337
+msgid "Disabled GFX"
+msgstr "GFX ausgeschalten"
+
+#: gui/ThemeEngine.cpp:338
+msgid "Standard Renderer (16bpp)"
+msgstr "Standard-Renderer (16bpp)"
+
+#: gui/ThemeEngine.cpp:340
+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/fr_FR.po b/po/fr_FR.po
new file mode 100644
index 0000000000..d4e9e9f53c
--- /dev/null
+++ b/po/fr_FR.po
@@ -0,0 +1,1486 @@
+# 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-12 17:44+0200\n"
+"PO-Revision-Date: 2010-07-09 18:17+0100\n"
+"Last-Translator: Thierry Crozat <criezy@scummvm.org>\n"
+"Language-Team: French <scummvm-devel@lists.sf.net>\n"
+"Language: Francais\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\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:266 gui/massadd.cpp:95 gui/options.cpp:972
+#: 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:102 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "Fermer"
+
+#: gui/GuiManager.cpp:105
+msgid "Mouse click"
+msgstr "Clic de souris"
+
+#: gui/GuiManager.cpp:108 base/main.cpp:285
+msgid "Display keyboard"
+msgstr "Afficher le clavier"
+
+#: gui/GuiManager.cpp:111 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:267 gui/launcher.cpp:873
+#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973
+#: 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:170
+msgid "Game"
+msgstr "Jeu"
+
+#: gui/launcher.cpp:173
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:173 gui/launcher.cpp:174
+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:177
+msgid "Name:"
+msgstr "Nom:"
+
+#: gui/launcher.cpp:177 gui/launcher.cpp:178
+msgid "Full title of the game"
+msgstr "Nom complet du jeu"
+
+#: gui/launcher.cpp:181
+msgid "Language:"
+msgstr "Langue:"
+
+#: gui/launcher.cpp:181 gui/launcher.cpp:182
+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:183 gui/launcher.cpp:194 gui/options.cpp:80
+#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<defaut>"
+
+#: gui/launcher.cpp:192
+msgid "Platform:"
+msgstr "Plateforme:"
+
+#: gui/launcher.cpp:192 gui/launcher.cpp:193
+msgid "Platform the game was originally designed for"
+msgstr "Plateforme pour laquelle votre jeu a été conçu"
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "Graphics"
+msgstr "Graphique"
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "GFX"
+msgstr "GFX"
+
+#: gui/launcher.cpp:206
+msgid "Override global graphic settings"
+msgstr "Utiliser des réglages graphiques spécifiques à ce jeux"
+
+#: gui/launcher.cpp:213 gui/options.cpp:873
+msgid "Audio"
+msgstr "Audio"
+
+#: gui/launcher.cpp:215
+msgid "Override global audio settings"
+msgstr "Utiliser des réglages audio spécifiques à ce jeux"
+
+#: gui/launcher.cpp:223 gui/options.cpp:877
+msgid "Volume"
+msgstr "Volume"
+
+#: gui/launcher.cpp:225
+msgid "Override global volume settings"
+msgstr "Utiliser des réglages de volume sonore spécifiques à ce jeux"
+
+#: gui/launcher.cpp:232 gui/options.cpp:885
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:234
+msgid "Override global MIDI settings"
+msgstr "Utiliser des réglages MIDI spécifiques à ce jeux"
+
+#: gui/launcher.cpp:244 gui/options.cpp:891
+msgid "Paths"
+msgstr "Chemins"
+
+#: gui/launcher.cpp:250
+msgid "Game Path:"
+msgstr "Chemin du Jeu:"
+
+#: gui/launcher.cpp:254 gui/options.cpp:904
+msgid "Extra Path:"
+msgstr "Extra:"
+
+#: gui/launcher.cpp:254 gui/launcher.cpp:255
+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:258
+msgid "Save Path:"
+msgstr "Sauvegardes:"
+
+#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898
+#: gui/options.cpp:899
+msgid "Specifies where your savegames are put"
+msgstr "Définie l'emplacement où les fichiers de sauvegarde sont créés"
+
+#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398
+#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486
+#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902
+#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996
+#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016
+#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050
+#: gui/options.cpp:1057 gui/options.cpp:1156
+msgid "None"
+msgstr "Aucun"
+
+#: gui/launcher.cpp:280 gui/launcher.cpp:357
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "Défaut"
+
+#: gui/launcher.cpp:391 gui/options.cpp:1150
+msgid "Select SoundFont"
+msgstr "Choisir une banque de sons"
+
+#: gui/launcher.cpp:410 gui/launcher.cpp:548
+msgid "Select directory with game data"
+msgstr "Sélectionner le répertoire contenant les données du jeu"
+
+#: gui/launcher.cpp:428
+msgid "Select additional game directory"
+msgstr "Sélectionner un répertoire supplémentaire"
+
+#: gui/launcher.cpp:440
+msgid "Select directory for saved games"
+msgstr "Sélectionner le répertoire pour les sauvegardes"
+
+#: gui/launcher.cpp:459
+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:500 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "~Q~uitter"
+
+#: gui/launcher.cpp:500
+msgid "Quit ScummVM"
+msgstr "Quitter ScummVM"
+
+#: gui/launcher.cpp:501
+msgid "A~b~out..."
+msgstr "À ~P~ropos..."
+
+#: gui/launcher.cpp:501
+msgid "About ScummVM"
+msgstr "À propos de ScummVM"
+
+#: gui/launcher.cpp:502
+msgid "~O~ptions..."
+msgstr "~O~ptions..."
+
+#: gui/launcher.cpp:502
+msgid "Change global ScummVM options"
+msgstr "Change les options globales de ScummVM"
+
+#: gui/launcher.cpp:504
+msgid "~S~tart"
+msgstr "~D~émarrer"
+
+#: gui/launcher.cpp:504
+msgid "Start selected game"
+msgstr "Démarre le jeu sélectionné"
+
+#: gui/launcher.cpp:507
+msgid "~L~oad..."
+msgstr "~C~harger"
+
+#: gui/launcher.cpp:507
+msgid "Load savegame for selected game"
+msgstr "Charge une sauvegarde pour le jeu sélectionné"
+
+#: gui/launcher.cpp:511
+msgid "~A~dd Game..."
+msgstr "~A~jouter..."
+
+#: gui/launcher.cpp:511
+msgid "Hold Shift for Mass Add"
+msgstr ""
+"Ajoute un jeu à la Liste. Maintenez Shift enfoncée pour un Ajout Massif"
+
+#: gui/launcher.cpp:513
+msgid "~E~dit Game..."
+msgstr "~E~diter..."
+
+#: gui/launcher.cpp:513
+msgid "Change game options"
+msgstr "Change les options du jeu"
+
+#: gui/launcher.cpp:515
+msgid "~R~emove Game"
+msgstr "~S~upprimer"
+
+#: gui/launcher.cpp:515
+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:522
+msgid "Search in game list"
+msgstr "Recherche dans la liste de jeux"
+
+#: gui/launcher.cpp:526 gui/launcher.cpp:1037
+msgid "Search:"
+msgstr "Filtre:"
+
+#: gui/launcher.cpp:529 gui/options.cpp:707
+msgid "Clear value"
+msgstr "Effacer la valeur"
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "Charger le jeu:"
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "Charger"
+
+#: gui/launcher.cpp:660
+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:661 gui/launcher.cpp:810
+#: 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:661 gui/launcher.cpp:810
+#: 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:708
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM n'a pas pu ouvrir le répertoire sélectionné."
+
+#: gui/launcher.cpp:720
+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:734
+msgid "Pick the game:"
+msgstr "Choisissez le jeu:"
+
+#: gui/launcher.cpp:810
+msgid "Do you really want to remove this game configuration?"
+msgstr "Voulez-vous vraiment supprimer ce jeu?"
+
+#: gui/launcher.cpp:873
+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:877
+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:989
+msgid "Mass Add..."
+msgstr "Ajout Massif..."
+
+#: gui/launcher.cpp:990
+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:614
+msgid "Graphics mode:"
+msgstr "Mode graphique:"
+
+#: gui/options.cpp:625
+msgid "Render mode:"
+msgstr "Mode de rendu:"
+
+#: gui/options.cpp:625 gui/options.cpp:626
+msgid "Special dithering modes supported by some games"
+msgstr "Mode spécial de tramage supporté par certains jeux"
+
+#: gui/options.cpp:635
+msgid "Fullscreen mode"
+msgstr "Plein écran"
+
+#: gui/options.cpp:638
+msgid "Aspect ratio correction"
+msgstr "Correction du rapport d'aspect"
+
+#: gui/options.cpp:638
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "Corrige le rapport d'aspect pour les jeu 320x200"
+
+#: gui/options.cpp:645
+msgid "Preferred Device:"
+msgstr "Sortie Préféré:"
+
+#: gui/options.cpp:645
+msgid "Music Device:"
+msgstr "Sortie Audio:"
+
+#: gui/options.cpp:645
+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:645 gui/options.cpp:646
+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:648
+#, fuzzy
+msgid "MT-32 Device:"
+msgstr "Sortie MT-32:"
+
+#: gui/options.cpp:648
+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:650
+msgid "GM Device:"
+msgstr "Sortie GM:"
+
+#: gui/options.cpp:650
+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:682
+msgid "AdLib emulator:"
+msgstr "Émulateur AdLib:"
+
+#: gui/options.cpp:682 gui/options.cpp:683
+msgid "AdLib is used for music in many games"
+msgstr "AdLib est utilisé pour la musique dans de nombreux jeux"
+
+#: gui/options.cpp:693
+msgid "Output rate:"
+msgstr "Fréquence:"
+
+#: gui/options.cpp:693 gui/options.cpp:694
+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:705
+msgid "SoundFont:"
+msgstr "Banque de sons:"
+
+#: gui/options.cpp:705 gui/options.cpp:706
+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:710
+msgid "Mixed AdLib/MIDI mode"
+msgstr "Mode mixe AdLib/MIDI"
+
+#: gui/options.cpp:710
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "Utiliser à la fois MIDI et AdLib"
+
+#: gui/options.cpp:713
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Roland MT-32 exacte (désactive l'émulation GM)"
+
+#: gui/options.cpp:713
+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:716
+msgid "Enable Roland GS Mode"
+msgstr "Activer le mode Roland GS"
+
+#: gui/options.cpp:716
+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:719
+msgid "MIDI gain:"
+msgstr "Gain MIDI:"
+
+#: gui/options.cpp:732
+msgid "Text and Speech:"
+msgstr "Dialogue:"
+
+#: gui/options.cpp:737 gui/options.cpp:743
+msgid "Speech"
+msgstr "Audio"
+
+#: gui/options.cpp:738 gui/options.cpp:744
+msgid "Subtitles"
+msgstr "Sous-titres"
+
+#: gui/options.cpp:739 gui/options.cpp:745
+msgid "Both"
+msgstr "Les deux"
+
+#: gui/options.cpp:743
+msgid "Spch"
+msgstr "Audio"
+
+#: gui/options.cpp:744
+msgid "Subs"
+msgstr "Subs"
+
+#: gui/options.cpp:745
+msgid "Show subtitles and play speech"
+msgstr "Affiche les sous-titres et joue les dialogues audio"
+
+#: gui/options.cpp:749
+msgid "Subtitle speed:"
+msgstr "Vitesse des ST:"
+
+#: gui/options.cpp:761
+msgid "Music volume:"
+msgstr "Volume Musique:"
+
+#: gui/options.cpp:768
+msgid "Mute All"
+msgstr "Silence"
+
+#: gui/options.cpp:771
+msgid "SFX volume:"
+msgstr "Volume Bruitage:"
+
+#: gui/options.cpp:771 gui/options.cpp:772
+msgid "Special sound effects volume"
+msgstr "Volume des effets spéciaux sonores"
+
+#: gui/options.cpp:778
+msgid "Speech volume:"
+msgstr "Volume Dialogues:"
+
+#: gui/options.cpp:898
+msgid "Save Path: "
+msgstr "Sauvegardes:"
+
+#: gui/options.cpp:901
+msgid "Theme Path:"
+msgstr "Thèmes:"
+
+#: gui/options.cpp:904 gui/options.cpp:905
+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:908
+msgid "Plugins Path:"
+msgstr "Plugins:"
+
+#: gui/options.cpp:913
+msgid "Misc"
+msgstr "Divers"
+
+#: gui/options.cpp:915
+msgid "Theme:"
+msgstr "Thème:"
+
+#: gui/options.cpp:919
+msgid "GUI Renderer:"
+msgstr "Interface:"
+
+#: gui/options.cpp:925
+msgid "Autosave:"
+msgstr "Sauvegarde auto:"
+
+#: gui/options.cpp:933
+msgid "Keys"
+msgstr "Touches"
+
+#: gui/options.cpp:940
+msgid "GUI Language:"
+msgstr "Langue:"
+
+#: gui/options.cpp:940
+msgid "Language of ScummVM GUI"
+msgstr "Langue de l'interface graphique de ScummVM"
+
+#: gui/options.cpp:945
+msgid "English"
+msgstr "Anglais"
+
+#: gui/options.cpp:1089
+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:1102
+msgid "Select directory for savegames"
+msgstr "Sélectionner le répertoire pour les sauvegardes"
+
+#: gui/options.cpp:1109
+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:1118
+msgid "Select directory for GUI themes"
+msgstr "Sélectionner le répertoire des thèmes d'interface"
+
+#: gui/options.cpp:1128
+msgid "Select directory for extra files"
+msgstr "Sélectionner le répertoire pour les fichiers suplémentaires"
+
+#: gui/options.cpp:1139
+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:337
+msgid "Disabled GFX"
+msgstr "GFX désactivé"
+
+#: gui/ThemeEngine.cpp:338
+msgid "Standard Renderer (16bpp)"
+msgstr "Standard (16bpp)"
+
+#: gui/ThemeEngine.cpp:340
+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..1d9a6c3268
--- /dev/null
+++ b/po/hu_HU.po
@@ -0,0 +1,1385 @@
+# 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-12 17:44+0200\n"
+"PO-Revision-Date: 2009-11-25 07:42-0500\n"
+"Last-Translator: Alex Bevilacqua <alexbevi@gmail.com>\n"
+"Language-Team: Hungarian\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=cp1250\n"
+"Content-Transfer-Encoding: 8bit\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:266 gui/massadd.cpp:95 gui/options.cpp:972
+#: 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:102 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr ""
+
+#: gui/GuiManager.cpp:105
+msgid "Mouse click"
+msgstr ""
+
+#: gui/GuiManager.cpp:108 base/main.cpp:285
+msgid "Display keyboard"
+msgstr ""
+
+#: gui/GuiManager.cpp:111 base/main.cpp:288
+msgid "Remap keys"
+msgstr ""
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr ""
+
+#: gui/KeysDialog.cpp:45 gui/launcher.cpp:267 gui/launcher.cpp:873
+#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973
+#: 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:170
+msgid "Game"
+msgstr ""
+
+#: gui/launcher.cpp:173
+msgid "ID:"
+msgstr ""
+
+#: gui/launcher.cpp:173 gui/launcher.cpp:174
+msgid ""
+"Short game identifier used for referring to savegames and running the game "
+"from the command line"
+msgstr ""
+
+#: gui/launcher.cpp:177
+msgid "Name:"
+msgstr ""
+
+#: gui/launcher.cpp:177 gui/launcher.cpp:178
+msgid "Full title of the game"
+msgstr ""
+
+#: gui/launcher.cpp:181
+msgid "Language:"
+msgstr ""
+
+#: gui/launcher.cpp:181 gui/launcher.cpp:182
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+
+#: gui/launcher.cpp:183 gui/launcher.cpp:194 gui/options.cpp:80
+#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<alapértelmezett>"
+
+#: gui/launcher.cpp:192
+msgid "Platform:"
+msgstr ""
+
+#: gui/launcher.cpp:192 gui/launcher.cpp:193
+msgid "Platform the game was originally designed for"
+msgstr ""
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "Graphics"
+msgstr "Grafikával"
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "GFX"
+msgstr ""
+
+#: gui/launcher.cpp:206
+msgid "Override global graphic settings"
+msgstr ""
+
+#: gui/launcher.cpp:213 gui/options.cpp:873
+msgid "Audio"
+msgstr "Hang"
+
+#: gui/launcher.cpp:215
+msgid "Override global audio settings"
+msgstr ""
+
+#: gui/launcher.cpp:223 gui/options.cpp:877
+msgid "Volume"
+msgstr "Volumene"
+
+#: gui/launcher.cpp:225
+msgid "Override global volume settings"
+msgstr ""
+
+#: gui/launcher.cpp:232 gui/options.cpp:885
+msgid "MIDI"
+msgstr ""
+
+#: gui/launcher.cpp:234
+msgid "Override global MIDI settings"
+msgstr ""
+
+#: gui/launcher.cpp:244 gui/options.cpp:891
+msgid "Paths"
+msgstr "Ösvények"
+
+#: gui/launcher.cpp:250
+#, fuzzy
+msgid "Game Path:"
+msgstr "Extra Útvonal:"
+
+#: gui/launcher.cpp:254 gui/options.cpp:904
+msgid "Extra Path:"
+msgstr "Extra Útvonal:"
+
+#: gui/launcher.cpp:254 gui/launcher.cpp:255
+msgid "Specifies path to additional data used the game"
+msgstr ""
+
+#: gui/launcher.cpp:258
+#, fuzzy
+msgid "Save Path:"
+msgstr "Extra Útvonal:"
+
+#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898
+#: gui/options.cpp:899
+msgid "Specifies where your savegames are put"
+msgstr ""
+
+#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398
+#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486
+#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902
+#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996
+#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016
+#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050
+#: gui/options.cpp:1057 gui/options.cpp:1156
+msgid "None"
+msgstr "Semmi"
+
+#: gui/launcher.cpp:280 gui/launcher.cpp:357
+#: backends/platform/wii/options.cpp:56
+#, fuzzy
+msgid "Default"
+msgstr "<alapértelmezett>"
+
+#: gui/launcher.cpp:391 gui/options.cpp:1150
+msgid "Select SoundFont"
+msgstr ""
+
+#: gui/launcher.cpp:410 gui/launcher.cpp:548
+msgid "Select directory with game data"
+msgstr ""
+
+#: gui/launcher.cpp:428
+msgid "Select additional game directory"
+msgstr ""
+
+#: gui/launcher.cpp:440
+msgid "Select directory for saved games"
+msgstr ""
+
+#: gui/launcher.cpp:459
+msgid "This game ID is already taken. Please choose another one."
+msgstr ""
+
+#: gui/launcher.cpp:500 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr ""
+
+#: gui/launcher.cpp:500
+msgid "Quit ScummVM"
+msgstr ""
+
+#: gui/launcher.cpp:501
+msgid "A~b~out..."
+msgstr ""
+
+#: gui/launcher.cpp:501
+msgid "About ScummVM"
+msgstr ""
+
+#: gui/launcher.cpp:502
+msgid "~O~ptions..."
+msgstr ""
+
+#: gui/launcher.cpp:502
+msgid "Change global ScummVM options"
+msgstr ""
+
+#: gui/launcher.cpp:504
+msgid "~S~tart"
+msgstr ""
+
+#: gui/launcher.cpp:504
+msgid "Start selected game"
+msgstr ""
+
+#: gui/launcher.cpp:507
+msgid "~L~oad..."
+msgstr ""
+
+#: gui/launcher.cpp:507
+msgid "Load savegame for selected game"
+msgstr ""
+
+#: gui/launcher.cpp:511
+msgid "~A~dd Game..."
+msgstr ""
+
+#: gui/launcher.cpp:511
+msgid "Hold Shift for Mass Add"
+msgstr ""
+
+#: gui/launcher.cpp:513
+msgid "~E~dit Game..."
+msgstr ""
+
+#: gui/launcher.cpp:513
+msgid "Change game options"
+msgstr ""
+
+#: gui/launcher.cpp:515
+msgid "~R~emove Game"
+msgstr ""
+
+#: gui/launcher.cpp:515
+msgid "Remove game from the list. The game data files stay intact"
+msgstr ""
+
+#: gui/launcher.cpp:522
+msgid "Search in game list"
+msgstr ""
+
+#: gui/launcher.cpp:526 gui/launcher.cpp:1037
+msgid "Search:"
+msgstr ""
+
+#: gui/launcher.cpp:529 gui/options.cpp:707
+msgid "Clear value"
+msgstr ""
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr ""
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr ""
+
+#: gui/launcher.cpp:660
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+
+#: gui/launcher.cpp:661 gui/launcher.cpp:810
+#: 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:661 gui/launcher.cpp:810
+#: 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:708
+msgid "ScummVM couldn't open the specified directory!"
+msgstr ""
+
+#: gui/launcher.cpp:720
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr ""
+
+#: gui/launcher.cpp:734
+msgid "Pick the game:"
+msgstr ""
+
+#: gui/launcher.cpp:810
+msgid "Do you really want to remove this game configuration?"
+msgstr ""
+
+#: gui/launcher.cpp:873
+msgid "This game does not support loading games from the launcher."
+msgstr ""
+
+#: gui/launcher.cpp:877
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr ""
+
+#: gui/launcher.cpp:989
+msgid "Mass Add..."
+msgstr ""
+
+#: gui/launcher.cpp:990
+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:614
+msgid "Graphics mode:"
+msgstr "Grafikus mód:"
+
+#: gui/options.cpp:625
+msgid "Render mode:"
+msgstr "Renderelési mód:"
+
+#: gui/options.cpp:625 gui/options.cpp:626
+msgid "Special dithering modes supported by some games"
+msgstr ""
+
+#: gui/options.cpp:635
+msgid "Fullscreen mode"
+msgstr "Teljes képerny s mód:"
+
+#: gui/options.cpp:638
+msgid "Aspect ratio correction"
+msgstr "Aspect adag korrekció"
+
+#: gui/options.cpp:638
+msgid "Correct aspect ratio for 320x200 games"
+msgstr ""
+
+#: gui/options.cpp:645
+msgid "Preferred Device:"
+msgstr ""
+
+#: gui/options.cpp:645
+#, fuzzy
+msgid "Music Device:"
+msgstr "Zene mennyiség:"
+
+#: gui/options.cpp:645
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr ""
+
+#: gui/options.cpp:645 gui/options.cpp:646
+msgid "Specifies output sound device or sound card emulator"
+msgstr ""
+
+#: gui/options.cpp:648
+#, fuzzy
+msgid "MT-32 Device:"
+msgstr "Zene mennyiség:"
+
+#: gui/options.cpp:648
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr ""
+
+#: gui/options.cpp:650
+msgid "GM Device:"
+msgstr ""
+
+#: gui/options.cpp:650
+msgid "Specifies default sound device for General MIDI output"
+msgstr ""
+
+#: gui/options.cpp:682
+msgid "AdLib emulator:"
+msgstr "AdLib vezet :"
+
+#: gui/options.cpp:682 gui/options.cpp:683
+msgid "AdLib is used for music in many games"
+msgstr ""
+
+#: gui/options.cpp:693
+msgid "Output rate:"
+msgstr "Kimeneti teljesítmény:"
+
+#: gui/options.cpp:693 gui/options.cpp:694
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+
+#: gui/options.cpp:705
+msgid "SoundFont:"
+msgstr ""
+
+#: gui/options.cpp:705 gui/options.cpp:706
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr ""
+
+#: gui/options.cpp:710
+msgid "Mixed AdLib/MIDI mode"
+msgstr "Vegyes AdLib/MIDI mód"
+
+#: gui/options.cpp:710
+msgid "Use both MIDI and AdLib sound generation"
+msgstr ""
+
+#: gui/options.cpp:713
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Igaz Roland MT-32 (megbénít GM emuláció)"
+
+#: gui/options.cpp:713
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+
+#: gui/options.cpp:716
+msgid "Enable Roland GS Mode"
+msgstr "Képessé Roland GS Mode"
+
+#: gui/options.cpp:716
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr ""
+
+#: gui/options.cpp:719
+msgid "MIDI gain:"
+msgstr "MIDI nyereség:"
+
+#: gui/options.cpp:732
+msgid "Text and Speech:"
+msgstr "Szöveg és beszéd:"
+
+#: gui/options.cpp:737 gui/options.cpp:743
+#, fuzzy
+msgid "Speech"
+msgstr "Csak a beszéd"
+
+#: gui/options.cpp:738 gui/options.cpp:744
+#, fuzzy
+msgid "Subtitles"
+msgstr "Csak feliratok"
+
+#: gui/options.cpp:739 gui/options.cpp:745
+msgid "Both"
+msgstr ""
+
+#: gui/options.cpp:743
+msgid "Spch"
+msgstr ""
+
+#: gui/options.cpp:744
+msgid "Subs"
+msgstr ""
+
+#: gui/options.cpp:745
+msgid "Show subtitles and play speech"
+msgstr ""
+
+#: gui/options.cpp:749
+msgid "Subtitle speed:"
+msgstr "Felirat sebesség:"
+
+#: gui/options.cpp:761
+msgid "Music volume:"
+msgstr "Zene mennyiség:"
+
+#: gui/options.cpp:768
+msgid "Mute All"
+msgstr "Muta Összes"
+
+#: gui/options.cpp:771
+msgid "SFX volume:"
+msgstr "SFX mennyisége"
+
+#: gui/options.cpp:771 gui/options.cpp:772
+msgid "Special sound effects volume"
+msgstr ""
+
+#: gui/options.cpp:778
+msgid "Speech volume:"
+msgstr "Beszéd mennyiség:"
+
+#: gui/options.cpp:898
+msgid "Save Path: "
+msgstr ""
+
+#: gui/options.cpp:901
+msgid "Theme Path:"
+msgstr ""
+
+#: gui/options.cpp:904 gui/options.cpp:905
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr ""
+
+#: gui/options.cpp:908
+msgid "Plugins Path:"
+msgstr ""
+
+#: gui/options.cpp:913
+msgid "Misc"
+msgstr ""
+
+#: gui/options.cpp:915
+msgid "Theme:"
+msgstr "Téma:"
+
+#: gui/options.cpp:919
+msgid "GUI Renderer:"
+msgstr "Leképez eszköz GUI:"
+
+#: gui/options.cpp:925
+msgid "Autosave:"
+msgstr "Automatikus mentés:"
+
+#: gui/options.cpp:933
+msgid "Keys"
+msgstr "Kulcsok"
+
+#: gui/options.cpp:940
+msgid "GUI Language:"
+msgstr ""
+
+#: gui/options.cpp:940
+msgid "Language of ScummVM GUI"
+msgstr ""
+
+#: gui/options.cpp:945
+msgid "English"
+msgstr ""
+
+#: gui/options.cpp:1089
+msgid "You have to restart ScummVM to take the effect."
+msgstr ""
+
+#: gui/options.cpp:1102
+msgid "Select directory for savegames"
+msgstr ""
+
+#: gui/options.cpp:1109
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr ""
+
+#: gui/options.cpp:1118
+msgid "Select directory for GUI themes"
+msgstr ""
+
+#: gui/options.cpp:1128
+msgid "Select directory for extra files"
+msgstr ""
+
+#: gui/options.cpp:1139
+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:337
+msgid "Disabled GFX"
+msgstr ""
+
+#: gui/ThemeEngine.cpp:338
+msgid "Standard Renderer (16bpp)"
+msgstr ""
+
+#: gui/ThemeEngine.cpp:340
+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..bbe6e92e95
--- /dev/null
+++ b/po/it_IT.po
@@ -0,0 +1,1362 @@
+# 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-12 17:44+0200\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"
+"Language: Italiano\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\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:266 gui/massadd.cpp:95 gui/options.cpp:972
+#: 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:102 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "Chiudi"
+
+#: gui/GuiManager.cpp:105
+msgid "Mouse click"
+msgstr "Clic del mouse"
+
+#: gui/GuiManager.cpp:108 base/main.cpp:285
+msgid "Display keyboard"
+msgstr "Mostra tastiera"
+
+#: gui/GuiManager.cpp:111 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:267 gui/launcher.cpp:873
+#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973
+#: 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:170
+msgid "Game"
+msgstr "Gioco"
+
+#: gui/launcher.cpp:173
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:173 gui/launcher.cpp:174
+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:177
+msgid "Name:"
+msgstr "Nome:"
+
+#: gui/launcher.cpp:177 gui/launcher.cpp:178
+msgid "Full title of the game"
+msgstr "Titolo completo del gioco"
+
+#: gui/launcher.cpp:181
+msgid "Language:"
+msgstr "Lingua:"
+
+#: gui/launcher.cpp:181 gui/launcher.cpp:182
+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:183 gui/launcher.cpp:194 gui/options.cpp:80
+#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<predefinito>"
+
+#: gui/launcher.cpp:192
+msgid "Platform:"
+msgstr "Piattaforma:"
+
+#: gui/launcher.cpp:192 gui/launcher.cpp:193
+msgid "Platform the game was originally designed for"
+msgstr "La piattaforma per la quale il gioco è stato concepito"
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "Graphics"
+msgstr "Grafica"
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "GFX"
+msgstr "Grafica"
+
+#: gui/launcher.cpp:206
+msgid "Override global graphic settings"
+msgstr "Ignora le impostazioni grafiche globali"
+
+#: gui/launcher.cpp:213 gui/options.cpp:873
+msgid "Audio"
+msgstr "Audio"
+
+#: gui/launcher.cpp:215
+msgid "Override global audio settings"
+msgstr "Ignora le impostazioni audio globali"
+
+#: gui/launcher.cpp:223 gui/options.cpp:877
+msgid "Volume"
+msgstr "Volume"
+
+#: gui/launcher.cpp:225
+msgid "Override global volume settings"
+msgstr "Ignora le impostazioni globali di volume"
+
+#: gui/launcher.cpp:232 gui/options.cpp:885
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:234
+msgid "Override global MIDI settings"
+msgstr "Ignora le impostazioni MIDI globali"
+
+#: gui/launcher.cpp:244 gui/options.cpp:891
+msgid "Paths"
+msgstr "Percorsi"
+
+#: gui/launcher.cpp:250
+msgid "Game Path:"
+msgstr "Percorso gioco:"
+
+#: gui/launcher.cpp:254 gui/options.cpp:904
+msgid "Extra Path:"
+msgstr "Percorso extra:"
+
+#: gui/launcher.cpp:254 gui/launcher.cpp:255
+msgid "Specifies path to additional data used the game"
+msgstr "Specifica il percorso di ulteriori dati usati dal gioco"
+
+#: gui/launcher.cpp:258
+msgid "Save Path:"
+msgstr "Salvataggi:"
+
+#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898
+#: gui/options.cpp:899
+msgid "Specifies where your savegames are put"
+msgstr "Specifica dove archiviare i salvataggi"
+
+#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398
+#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486
+#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902
+#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996
+#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016
+#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050
+#: gui/options.cpp:1057 gui/options.cpp:1156
+msgid "None"
+msgstr "Nessuno"
+
+#: gui/launcher.cpp:280 gui/launcher.cpp:357
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "Predefinito"
+
+#: gui/launcher.cpp:391 gui/options.cpp:1150
+msgid "Select SoundFont"
+msgstr "Seleziona SoundFont"
+
+#: gui/launcher.cpp:410 gui/launcher.cpp:548
+msgid "Select directory with game data"
+msgstr "Seleziona la cartella contenente i file di gioco"
+
+#: gui/launcher.cpp:428
+msgid "Select additional game directory"
+msgstr "Seleziona la cartella di gioco aggiuntiva"
+
+#: gui/launcher.cpp:440
+msgid "Select directory for saved games"
+msgstr "Seleziona la cartella dei salvataggi"
+
+#: gui/launcher.cpp:459
+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:500 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "C~h~iudi"
+
+#: gui/launcher.cpp:500
+msgid "Quit ScummVM"
+msgstr "Chiudi ScummVM"
+
+#: gui/launcher.cpp:501
+msgid "A~b~out..."
+msgstr "~I~nfo..."
+
+#: gui/launcher.cpp:501
+msgid "About ScummVM"
+msgstr "Informazioni su ScummVM"
+
+#: gui/launcher.cpp:502
+msgid "~O~ptions..."
+msgstr "~O~pzioni..."
+
+#: gui/launcher.cpp:502
+msgid "Change global ScummVM options"
+msgstr "Modifica le opzioni globali di ScummVM"
+
+#: gui/launcher.cpp:504
+msgid "~S~tart"
+msgstr "~G~ioca"
+
+#: gui/launcher.cpp:504
+msgid "Start selected game"
+msgstr "Esegue il gioco selezionato"
+
+#: gui/launcher.cpp:507
+msgid "~L~oad..."
+msgstr "~C~arica..."
+
+#: gui/launcher.cpp:507
+msgid "Load savegame for selected game"
+msgstr "Carica un salvataggio del gioco selezionato"
+
+#: gui/launcher.cpp:511
+msgid "~A~dd Game..."
+msgstr "~A~ggiungi gioco..."
+
+#: gui/launcher.cpp:511
+msgid "Hold Shift for Mass Add"
+msgstr "Tieni premuto Shift per l'aggiunta in massa"
+
+#: gui/launcher.cpp:513
+msgid "~E~dit Game..."
+msgstr "~M~odifica gioco..."
+
+#: gui/launcher.cpp:513
+msgid "Change game options"
+msgstr "Modifica le opzioni di gioco"
+
+#: gui/launcher.cpp:515
+msgid "~R~emove Game"
+msgstr "~R~imuovi gioco"
+
+#: gui/launcher.cpp:515
+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:522
+msgid "Search in game list"
+msgstr "Cerca nella lista dei giochi"
+
+#: gui/launcher.cpp:526 gui/launcher.cpp:1037
+msgid "Search:"
+msgstr "Cerca:"
+
+#: gui/launcher.cpp:529 gui/options.cpp:707
+msgid "Clear value"
+msgstr "Cancella"
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "Carica gioco:"
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "Carica"
+
+#: gui/launcher.cpp:660
+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:661 gui/launcher.cpp:810
+#: 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:661 gui/launcher.cpp:810
+#: 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:708
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM non ha potuto aprire la cartella specificata!"
+
+#: gui/launcher.cpp:720
+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:734
+msgid "Pick the game:"
+msgstr "Scegli il gioco:"
+
+#: gui/launcher.cpp:810
+msgid "Do you really want to remove this game configuration?"
+msgstr "Sei sicuro di voler rimuovere questa configurazione di gioco?"
+
+#: gui/launcher.cpp:873
+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:877
+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:989
+msgid "Mass Add..."
+msgstr "Agg. in massa..."
+
+#: gui/launcher.cpp:990
+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:614
+msgid "Graphics mode:"
+msgstr "Modalità:"
+
+#: gui/options.cpp:625
+msgid "Render mode:"
+msgstr "Resa grafica:"
+
+#: gui/options.cpp:625 gui/options.cpp:626
+msgid "Special dithering modes supported by some games"
+msgstr "Modalità di resa grafica speciali supportate da alcuni giochi"
+
+#: gui/options.cpp:635
+msgid "Fullscreen mode"
+msgstr "Modalità a schermo intero"
+
+#: gui/options.cpp:638
+msgid "Aspect ratio correction"
+msgstr "Correzione proporzioni"
+
+#: gui/options.cpp:638
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "Corregge le proporzioni dei giochi 320x200"
+
+#: gui/options.cpp:645
+msgid "Preferred Device:"
+msgstr "Disp. preferito:"
+
+#: gui/options.cpp:645
+#, fuzzy
+msgid "Music Device:"
+msgstr "Dispositivo GM:"
+
+#: gui/options.cpp:645
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr ""
+"Specifica il dispositivo audio o l'emulatore della scheda audio preferiti"
+
+#: gui/options.cpp:645 gui/options.cpp:646
+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:648
+#, fuzzy
+msgid "MT-32 Device:"
+msgstr "Disposit. MT32:"
+
+#: gui/options.cpp:648
+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:650
+msgid "GM Device:"
+msgstr "Dispositivo GM:"
+
+#: gui/options.cpp:650
+msgid "Specifies default sound device for General MIDI output"
+msgstr "Specifica il dispositivo audio predefinito per l'output General MIDI"
+
+#: gui/options.cpp:682
+msgid "AdLib emulator:"
+msgstr "Emulatore AdLib:"
+
+#: gui/options.cpp:682 gui/options.cpp:683
+msgid "AdLib is used for music in many games"
+msgstr "AdLib è utilizzato per la musica in molti giochi"
+
+#: gui/options.cpp:693
+msgid "Output rate:"
+msgstr "Frequenza:"
+
+#: gui/options.cpp:693 gui/options.cpp:694
+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:705
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:705 gui/options.cpp:706
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr "SoundFont è supportato da alcune schede audio, Fluidsynth e Timidity"
+
+#: gui/options.cpp:710
+msgid "Mixed AdLib/MIDI mode"
+msgstr "Modalità mista AdLib/MIDI"
+
+#: gui/options.cpp:710
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "Utilizza generazione di suono sia MIDI che AdLib"
+
+#: gui/options.cpp:713
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "Roland MT-32 effettivo (disattiva emulazione GM)"
+
+#: gui/options.cpp:713
+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:716
+msgid "Enable Roland GS Mode"
+msgstr "Attiva la modalità Roland GS"
+
+#: gui/options.cpp:716
+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:719
+msgid "MIDI gain:"
+msgstr "Guadagno MIDI:"
+
+#: gui/options.cpp:732
+msgid "Text and Speech:"
+msgstr "Testo e voci:"
+
+#: gui/options.cpp:737 gui/options.cpp:743
+msgid "Speech"
+msgstr "Voci"
+
+#: gui/options.cpp:738 gui/options.cpp:744
+msgid "Subtitles"
+msgstr "Sottotitoli"
+
+#: gui/options.cpp:739 gui/options.cpp:745
+msgid "Both"
+msgstr "Entrambi"
+
+#: gui/options.cpp:743
+msgid "Spch"
+msgstr "Voci"
+
+#: gui/options.cpp:744
+msgid "Subs"
+msgstr "Sub"
+
+#: gui/options.cpp:745
+msgid "Show subtitles and play speech"
+msgstr "Mostra i sottotitoli e attiva le voci"
+
+#: gui/options.cpp:749
+msgid "Subtitle speed:"
+msgstr "Velocità testo:"
+
+#: gui/options.cpp:761
+msgid "Music volume:"
+msgstr "Volume musica:"
+
+#: gui/options.cpp:768
+msgid "Mute All"
+msgstr "Disattiva audio"
+
+#: gui/options.cpp:771
+msgid "SFX volume:"
+msgstr "Volume effetti:"
+
+#: gui/options.cpp:771 gui/options.cpp:772
+msgid "Special sound effects volume"
+msgstr "Volume degli effetti sonori"
+
+#: gui/options.cpp:778
+msgid "Speech volume:"
+msgstr "Volume voci:"
+
+#: gui/options.cpp:898
+msgid "Save Path: "
+msgstr "Salvataggi:"
+
+#: gui/options.cpp:901
+msgid "Theme Path:"
+msgstr "Percorso tema:"
+
+#: gui/options.cpp:904 gui/options.cpp:905
+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:908
+msgid "Plugins Path:"
+msgstr "Percorso plugin:"
+
+#: gui/options.cpp:913
+msgid "Misc"
+msgstr "Varie"
+
+#: gui/options.cpp:915
+msgid "Theme:"
+msgstr "Tema:"
+
+#: gui/options.cpp:919
+msgid "GUI Renderer:"
+msgstr "Renderer GUI:"
+
+#: gui/options.cpp:925
+msgid "Autosave:"
+msgstr "Autosalva:"
+
+#: gui/options.cpp:933
+msgid "Keys"
+msgstr "Tasti"
+
+#: gui/options.cpp:940
+msgid "GUI Language:"
+msgstr "Lingua GUI:"
+
+#: gui/options.cpp:940
+msgid "Language of ScummVM GUI"
+msgstr "Lingua dell'interfaccia grafica di ScummVM"
+
+#: gui/options.cpp:945
+msgid "English"
+msgstr "Inglese"
+
+#: gui/options.cpp:1089
+msgid "You have to restart ScummVM to take the effect."
+msgstr "Devi riavviare ScummVM affinché le modifiche abbiano effetto."
+
+#: gui/options.cpp:1102
+msgid "Select directory for savegames"
+msgstr "Seleziona la cartella per i salvataggi"
+
+#: gui/options.cpp:1109
+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:1118
+msgid "Select directory for GUI themes"
+msgstr "Seleziona la cartella dei temi dell'interfaccia"
+
+#: gui/options.cpp:1128
+msgid "Select directory for extra files"
+msgstr "Seleziona la cartella dei file aggiuntivi"
+
+#: gui/options.cpp:1139
+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:337
+msgid "Disabled GFX"
+msgstr "Grafica disattivata"
+
+#: gui/ThemeEngine.cpp:338
+msgid "Standard Renderer (16bpp)"
+msgstr "Renderer standard (16bpp)"
+
+#: gui/ThemeEngine.cpp:340
+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..2d4a96b63c
--- /dev/null
+++ b/po/ru_RU.po
@@ -0,0 +1,1361 @@
+# 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-12 17:44+0200\n"
+"PO-Revision-Date: 2010-06-13 20:55+0300\n"
+"Last-Translator: Eugene Sandulenko <sev@scummvm.org>\n"
+"Language-Team: Russian\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-5\n"
+"Content-Transfer-Encoding: 8bit\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:266 gui/massadd.cpp:95 gui/options.cpp:972
+#: 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:102 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr "·ÐÚàëâì"
+
+#: gui/GuiManager.cpp:105
+msgid "Mouse click"
+msgstr "ºÛØÚ Üëèìî"
+
+#: gui/GuiManager.cpp:108 base/main.cpp:285
+msgid "Display keyboard"
+msgstr "¿ÞÚÐ×Ðâì ÚÛÐÒØÐâãàã"
+
+#: gui/GuiManager.cpp:111 base/main.cpp:288
+msgid "Remap keys"
+msgstr "¿ÕàÕÝÐ×ÝÐçØâì ÚÛÐÒØèØ"
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr "½Ð×ÝÐçØâì"
+
+#: gui/KeysDialog.cpp:45 gui/launcher.cpp:267 gui/launcher.cpp:873
+#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973
+#: 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:170
+msgid "Game"
+msgstr "¸ÓàÐ"
+
+#: gui/launcher.cpp:173
+msgid "ID:"
+msgstr "ID:"
+
+#: gui/launcher.cpp:173 gui/launcher.cpp:174
+msgid ""
+"Short game identifier used for referring to savegames and running the game "
+"from the command line"
+msgstr ""
+"ºÞàÞâÚØÙ ØÔÕÝâØäØÚÐâÞà, ØáßÞÛì×ãÕÜëÙ ÔÛï ØÜÕÝ áÞåàÐÝÕÝØÙ ØÓà Ø ÔÛï ×ÐßãáÚÐ "
+"Ø× ÚÞÜÐÝÔÝÞÙ áâàÞÚØ"
+
+#: gui/launcher.cpp:177
+msgid "Name:"
+msgstr "½Ð×ÒÐÝØÕ:"
+
+#: gui/launcher.cpp:177 gui/launcher.cpp:178
+msgid "Full title of the game"
+msgstr "¿ÞÛÝÞÕ ÝÐ×ÒÐÝØÕ ØÓàë"
+
+#: gui/launcher.cpp:181
+msgid "Language:"
+msgstr "Ï×ëÚ:"
+
+#: gui/launcher.cpp:181 gui/launcher.cpp:182
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+"Ï×ëÚ ØÓàë. ¸×ÜÕÝÕÝØÕ íâÞÓÞ ßÐàÐÜÕâàÐ ÝÕ ßàÕÒàÐâØâ ØÓàã ÝÐ ÐÝÓÛØÙáÚÞÜ Ò "
+"àãááÚãî"
+
+#: gui/launcher.cpp:183 gui/launcher.cpp:194 gui/options.cpp:80
+#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr "<ßÞ ãÜÞÛçÐÝØî>"
+
+#: gui/launcher.cpp:192
+msgid "Platform:"
+msgstr "¿ÛÐâäÞàÜÐ:"
+
+#: gui/launcher.cpp:192 gui/launcher.cpp:193
+msgid "Platform the game was originally designed for"
+msgstr "¿ÛÐâäÞàÜÐ, ÔÛï ÚÞâÞàÞÙ ØÓàÐ ÑëÛÐ Ø×ÝÐçÐÛìÝÞ àÐ×àÐÑÞâÐÝÐ"
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "Graphics"
+msgstr "³àÐäØÚÐ"
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "GFX"
+msgstr "³àä"
+
+#: gui/launcher.cpp:206
+msgid "Override global graphic settings"
+msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ ÓàÐäØÚØ"
+
+#: gui/launcher.cpp:213 gui/options.cpp:873
+msgid "Audio"
+msgstr "°ãÔØÞ"
+
+#: gui/launcher.cpp:215
+msgid "Override global audio settings"
+msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ ÐãÔØÞ"
+
+#: gui/launcher.cpp:223 gui/options.cpp:877
+msgid "Volume"
+msgstr "³àÞÜÚÞáâì"
+
+#: gui/launcher.cpp:225
+msgid "Override global volume settings"
+msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ ÓàÞÜÚÞáâØ"
+
+#: gui/launcher.cpp:232 gui/options.cpp:885
+msgid "MIDI"
+msgstr "MIDI"
+
+#: gui/launcher.cpp:234
+msgid "Override global MIDI settings"
+msgstr "¿ÕàÕÚàëâì ÓÛÞÑÐÛìÝëÕ ãáâÐÝÞÒÚØ MIDI"
+
+#: gui/launcher.cpp:244 gui/options.cpp:891
+msgid "Paths"
+msgstr "¿ãâØ"
+
+#: gui/launcher.cpp:250
+msgid "Game Path:"
+msgstr "¿ãâì Ú ØÓàÕ: "
+
+#: gui/launcher.cpp:254 gui/options.cpp:904
+msgid "Extra Path:"
+msgstr "´Þß. ßãâì:"
+
+#: gui/launcher.cpp:254 gui/launcher.cpp:255
+msgid "Specifies path to additional data used the game"
+msgstr "ÃÚÐ×ëÒÐÕâ ßãâì Ú ÔÞßÞÛÝØâÕÛìÝëÜ äÐÙÛÐÜ ÔÐÝÝëå ÔÛï ØÓàë"
+
+#: gui/launcher.cpp:258
+msgid "Save Path:"
+msgstr "¿ãâì áÞåà.: "
+
+#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898
+#: gui/options.cpp:899
+msgid "Specifies where your savegames are put"
+msgstr "ÃÚÐ×ëÒÐÕâ ßãâì Ú áÞåàÐÝÕÝØïÜ ØÓàë"
+
+#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398
+#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486
+#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902
+#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996
+#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016
+#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050
+#: gui/options.cpp:1057 gui/options.cpp:1156
+msgid "None"
+msgstr "½Õ ×ÐÔÐÝ"
+
+#: gui/launcher.cpp:280 gui/launcher.cpp:357
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr "¿Þ ãÜÞÛçÐÝØî"
+
+#: gui/launcher.cpp:391 gui/options.cpp:1150
+msgid "Select SoundFont"
+msgstr "²ëÑÕàØâÕ SoundFont"
+
+#: gui/launcher.cpp:410 gui/launcher.cpp:548
+msgid "Select directory with game data"
+msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî á äÐÙÛÐÜØ ØÓàë"
+
+#: gui/launcher.cpp:428
+msgid "Select additional game directory"
+msgstr "²ëÑÕàØâÕ ÔÞßÞÛÝØâÕÛìÝãî ÔØàÕÚâÞàØî ØÓàë"
+
+#: gui/launcher.cpp:440
+msgid "Select directory for saved games"
+msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî ÔÛï áÞåàÐÝÕÝØÙ"
+
+#: gui/launcher.cpp:459
+msgid "This game ID is already taken. Please choose another one."
+msgstr "ÍâÞâ ID ØÓàë ãÖÕ ØáßÞÛì×ãÕâáï. ¿ÞÖÐÛãÙáâÐ, ÒëÑÕàØâÕ ÔàãÓÞÙ."
+
+#: gui/launcher.cpp:500 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr "~²~ëåÞÔ"
+
+#: gui/launcher.cpp:500
+msgid "Quit ScummVM"
+msgstr "²ëåÞÔ Ø× ScummVM"
+
+#: gui/launcher.cpp:501
+msgid "A~b~out..."
+msgstr "¾ ß~à~ÞÓàÐÜÜÕ..."
+
+#: gui/launcher.cpp:501
+msgid "About ScummVM"
+msgstr "¾ ßàÞÓàÐÜÜÕ ScummVM"
+
+#: gui/launcher.cpp:502
+msgid "~O~ptions..."
+msgstr "~¾~ßæØØ..."
+
+#: gui/launcher.cpp:502
+msgid "Change global ScummVM options"
+msgstr "¸×ÜÕÝØâì ÓÛÞÑÐÛìÝëÕ ÞßæØØ ScummVM"
+
+#: gui/launcher.cpp:504
+msgid "~S~tart"
+msgstr "¿~ã~áÚ"
+
+#: gui/launcher.cpp:504
+msgid "Start selected game"
+msgstr "·ÐßãáâØâì ÒëÑàÐÝÝãî ØÓàã"
+
+#: gui/launcher.cpp:507
+msgid "~L~oad..."
+msgstr "~·~ÐÓà...."
+
+#: gui/launcher.cpp:507
+msgid "Load savegame for selected game"
+msgstr "·ÐÓàã×Øâì áÞåàÝÕÝØÕ ÔÛï ÒëÑàÐÝÝÞÙ ØÓàë"
+
+#: gui/launcher.cpp:511
+msgid "~A~dd Game..."
+msgstr "~´~ÞÑ. ØÓàã..."
+
+#: gui/launcher.cpp:511
+msgid "Hold Shift for Mass Add"
+msgstr "ÃÔÕàÖØÒÐÙâÕ ÚÛÐÒØèã Shift ÔÛï âÞÓÞ, çâÞÑë ÔÞÑÐÒØâì ÝÕáÚÞÛìÚÞ ØÓà"
+
+#: gui/launcher.cpp:513
+msgid "~E~dit Game..."
+msgstr "¸×~Ü~. ØÓàã..."
+
+#: gui/launcher.cpp:513
+msgid "Change game options"
+msgstr "¸×ÜÕÝØâì ÞßæØØ ØÓàë"
+
+#: gui/launcher.cpp:515
+msgid "~R~emove Game"
+msgstr "~Ã~ÔÐÛØâì ØÓàã"
+
+#: gui/launcher.cpp:515
+msgid "Remove game from the list. The game data files stay intact"
+msgstr "ÃÔÐÛØâì ØÓàã Ø× áßØáÚÐ. ½Õ ãÔÐÛïÕâ ØÓàã á ÖÕáâÚÞÓÞ ÔØáÚÐ"
+
+#: gui/launcher.cpp:522
+msgid "Search in game list"
+msgstr "¿ÞØáÚ Ò áßØáÚÕ ØÓà"
+
+#: gui/launcher.cpp:526 gui/launcher.cpp:1037
+msgid "Search:"
+msgstr "¿ÞØáÚ:"
+
+#: gui/launcher.cpp:529 gui/options.cpp:707
+msgid "Clear value"
+msgstr "¾çØáâØâì ×ÝÐçÕÝØÕ"
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr "·ÐÓàã×Øâì ØÓàã:"
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr "·ÐÓàã×Øâì"
+
+#: gui/launcher.cpp:660
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+"²ë ÔÕÙáâÒØâÕÛìÝÞ åÞâØâÕ ×ÐßãáâØâì ÔÕâÕÚâÞà ÒáÕå ØÓà? ÍâÞ ßÞâÕÝæØÐÛìÝÞ ÜÞÖÕâ "
+"ÔÞÑÐÒØâì ÑÞÛìèÞÕ ÚÞÛØçÕáâÒÞ ØÓà."
+
+#: gui/launcher.cpp:661 gui/launcher.cpp:810
+#: 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:661 gui/launcher.cpp:810
+#: 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:708
+msgid "ScummVM couldn't open the specified directory!"
+msgstr "ScummVM ÝÕ ÜÞÖÕâ ÞâÚàëâì ãÚÐ×ÐÝÝãî ÔØàÕÚâÞàØî!"
+
+#: gui/launcher.cpp:720
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr "ScummVM ÝÕ ÜÞÖÕâ ÝÐÙâØ ØÓàã Ò ãÚÐ×ÐÝÝÞÙ ÔØàÕÚâÞàØØ!"
+
+#: gui/launcher.cpp:734
+msgid "Pick the game:"
+msgstr "²ëÑÕàØâÕ ØÓàã:"
+
+#: gui/launcher.cpp:810
+msgid "Do you really want to remove this game configuration?"
+msgstr "²ë ÔÕÙáâÒØâÕÛìÝÞ åÞâØâÕ ãÔÐÛØâì ãáâÐÝÞÒÚØ ÔÛï íâÞÙ ØÓàë?"
+
+#: gui/launcher.cpp:873
+msgid "This game does not support loading games from the launcher."
+msgstr "ÍâÐ ØÓàÐ ÝÕ ßÞÔÔÕàÖØÒÐÕâ ×ÐÓàã×Úã áÞåàÐÝÕÝØÙ çÕàÕ× ÓÛÐÒÝÞÕ ÜÕÝî."
+
+#: gui/launcher.cpp:877
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr "ScummVM ÝÕ áÜÞÓ ÝÐÙâØ ÔÒØÖÞÚ ÔÛï ×ÐßãáÚÐ ÒëÑàÐÝÝÞÙ ØÓàë!"
+
+#: gui/launcher.cpp:989
+msgid "Mass Add..."
+msgstr "´ÞÑ. ÜÝÞÓÞ..."
+
+#: gui/launcher.cpp:990
+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:614
+msgid "Graphics mode:"
+msgstr "³àÐäØçÕáÚØÙ àÕÖØÜ:"
+
+#: gui/options.cpp:625
+msgid "Render mode:"
+msgstr "ÀÕÖØÜ àÐáâàØàÞÒÐÝØï:"
+
+#: gui/options.cpp:625 gui/options.cpp:626
+msgid "Special dithering modes supported by some games"
+msgstr "ÁßÕæØÐÛìÝëÕ àÕÖØÜë àÕÝÔÕàØÝÓÐ, ßÞÔÔÕàÖØÒÐÕÜëÕ ÝÕÚÞâÞàëÜØ ØÓàÐÜØ"
+
+#: gui/options.cpp:635
+msgid "Fullscreen mode"
+msgstr "¿ÞÛÝÞíÚàÐÝÝëÙ àÕÖØÜ"
+
+#: gui/options.cpp:638
+msgid "Aspect ratio correction"
+msgstr "ºÞààÕÚæØï áÞÞâÝÞèÕÝØï áâÞàÞÝ"
+
+#: gui/options.cpp:638
+msgid "Correct aspect ratio for 320x200 games"
+msgstr "ºÞààÕÚâØàÞÒÐâì áÞÞâÝÞèÕÝØÕ áâÞàÞÝ ÔÛï ØÓà á àÐ×àÕèÕÝØÕÜ 320x200"
+
+#: gui/options.cpp:645
+msgid "Preferred Device:"
+msgstr "¿àÕÔßÞçØâÐÕÜÞÕ ãáâàÞÙáâÒÞ:"
+
+#: gui/options.cpp:645
+#, fuzzy
+msgid "Music Device:"
+msgstr "ÃáâàÞÙâáÒÞ GM:"
+
+#: gui/options.cpp:645
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr "ÃÚÐ×ëÒÐÕâ ÒëåÞÔÝÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ØÛØ íÜãÛïâÞà ×ÒãÚÞÒÞÙ ÚÐàâë"
+
+#: gui/options.cpp:645 gui/options.cpp:646
+msgid "Specifies output sound device or sound card emulator"
+msgstr "ÃÚÐ×ëÒÐÕâ ÒëåÞÔÝÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ØÛØ íÜãÛïâÞà ×ÒãÚÞÒÞÙ ÚÐàâë"
+
+#: gui/options.cpp:648
+#, fuzzy
+msgid "MT-32 Device:"
+msgstr "ÃáâàÞÙáâÒÞ MT32:"
+
+#: gui/options.cpp:648
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr ""
+"ÃÚÐ×ëÒÐÕâ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ßÞ ãÜÞÛçÐÝØï ÔÛï ÒëÒÞÔÐ ÝÐ Roland MT-32/LAPC1/"
+"CM32l/CM64"
+
+#: gui/options.cpp:650
+msgid "GM Device:"
+msgstr "ÃáâàÞÙâáÒÞ GM:"
+
+#: gui/options.cpp:650
+msgid "Specifies default sound device for General MIDI output"
+msgstr "ÃÚÐ×ëÒÐÕâ ÒëåÞÔÝÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ ÔÛï MIDI"
+
+#: gui/options.cpp:682
+msgid "AdLib emulator:"
+msgstr "ÍÜãÛïâÞà AdLib:"
+
+#: gui/options.cpp:682 gui/options.cpp:683
+msgid "AdLib is used for music in many games"
+msgstr "·ÒãÚÞÒÐï ÚÐàâÐ AdLib ØáßÞÛì×ãÕâáï ÜÝÞÓØÜØ ØÓàÐÜØ"
+
+#: gui/options.cpp:693
+msgid "Output rate:"
+msgstr "²ëåÞÔÝÐï çÐáâÞâÐ:"
+
+#: gui/options.cpp:693 gui/options.cpp:694
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+"±¾ÛìèØÕ ×ÝÐçÕÝØï ×ÐÔÐîâ ÛãçèÕÕ ÚÐçÕáâÒÞ ×ÒãÚÐ, ÞÔÝÐÚÞ ÞÝØ ÜÞÓãâ ÝÕ "
+"ßÞÔÔÕàÖØÒÐâìáï ÒÐèÕÙ ×ÒãÚÞÒÞÙ ÚÐàâÞÙ"
+
+#: gui/options.cpp:705
+msgid "SoundFont:"
+msgstr "SoundFont:"
+
+#: gui/options.cpp:705 gui/options.cpp:706
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr ""
+"SoundFontë ßÞÔÔÕàÔÖØÒÐîâáï ÝÕÚÞâÞàëÜØ ×ÒãÚÞÒëÜØ ÚÐàâÐÜØ, Fluidsynth Ø "
+"Timidity"
+
+#: gui/options.cpp:710
+msgid "Mixed AdLib/MIDI mode"
+msgstr "ÁÜÕèÐÝÝëÙ àÕÖØÜ AdLib/MIDI"
+
+#: gui/options.cpp:710
+msgid "Use both MIDI and AdLib sound generation"
+msgstr "¸áßÞÛì×ÞÒÐâì Ø MIDI Ø AdLib ÔÛï ÓÕÝÕàÐæØØ ×ÒãÚÐ"
+
+#: gui/options.cpp:713
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr "½ÐáâÞïéØÙ Roland MT-32 (×ÐßàÕâØâì íÜãÛïæØî GM)"
+
+#: gui/options.cpp:713
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+"¾âÜÕâìâÕ, ÕáÛØ ã ÒÐá ßÞÔÚÛîçÕÝÞ Roland-áÞÒÜÕáâØÜÞÕ ×ÒãÚÞÒÞÕ ãáâàÞÙáâÒÞ Ø Òë "
+"åÞâØâÕ ÕÓÞ ØáßÞÛì×ÞÒÐâì"
+
+#: gui/options.cpp:716
+msgid "Enable Roland GS Mode"
+msgstr "²ÚÛîçØâì àÕÖØÜ Roland GS"
+
+#: gui/options.cpp:716
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr ""
+"²ëÚÛîçÐÕâ ÜÐßßØÝÓ General MIDI ÔÛï ØÓà á ×ÒãÚÞÒÞÙ ÔÞàÞÖÚÞÙ ÔÛï Roland MT-32"
+
+#: gui/options.cpp:719
+msgid "MIDI gain:"
+msgstr "ÃáØÛÕÝØÕ MIDI:"
+
+#: gui/options.cpp:732
+msgid "Text and Speech:"
+msgstr "ÂÕÚáâ Ø Þ×ÒãçÚÐ:"
+
+#: gui/options.cpp:737 gui/options.cpp:743
+msgid "Speech"
+msgstr "¾×ÒãçÚÐ"
+
+#: gui/options.cpp:738 gui/options.cpp:744
+msgid "Subtitles"
+msgstr "ÁãÑâØâàë"
+
+#: gui/options.cpp:739 gui/options.cpp:745
+msgid "Both"
+msgstr "²áñ"
+
+#: gui/options.cpp:743
+msgid "Spch"
+msgstr "¾×Ò"
+
+#: gui/options.cpp:744
+msgid "Subs"
+msgstr "狄"
+
+#: gui/options.cpp:745
+msgid "Show subtitles and play speech"
+msgstr "¿ÞÚÐ×ëÒÐâì áãÑâØâàë Ø ÒÞáßàÞØ×ÒÞÔØâì àÕçì"
+
+#: gui/options.cpp:749
+msgid "Subtitle speed:"
+msgstr "ÁÚÞàÞáâì áãÑâØâàÞÒ:"
+
+#: gui/options.cpp:761
+msgid "Music volume:"
+msgstr "³àÞÜÚÞáâì Üã×ëÚØ:"
+
+#: gui/options.cpp:768
+msgid "Mute All"
+msgstr "²ëÚÛîçØâì Òáñ"
+
+#: gui/options.cpp:771
+msgid "SFX volume:"
+msgstr "³àÞÜÚÞáâì íääÕÚâÞÒ:"
+
+#: gui/options.cpp:771 gui/options.cpp:772
+msgid "Special sound effects volume"
+msgstr "³àÞÜÚÞáâì áßÕæØÐÛìÝëå ×ÒãÚÞÒëå íääÕÚâÞÒ"
+
+#: gui/options.cpp:778
+msgid "Speech volume:"
+msgstr "³àÞÜÚÞáâì Þ×ÒãçÚØ:"
+
+#: gui/options.cpp:898
+msgid "Save Path: "
+msgstr "¿ãâì ÔÛï áÞåàÐÝÕÝØÙ: "
+
+#: gui/options.cpp:901
+msgid "Theme Path:"
+msgstr "¿ãâì Ú âÕÜÐÜ:"
+
+#: gui/options.cpp:904 gui/options.cpp:905
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr ""
+"ÃÚÐ×ëÒÐÕâ ßãâì Ú ÔÞßÞÛÝØâÕÛìÝëÜ äÐÙÛÐÜ ÔÐÝÝëå, ØáßÞÛì×ãÕÜëå ÒáÕÜØ ØÓàÐÜØ, "
+"ÛØÑÞ ScummVM"
+
+#: gui/options.cpp:908
+msgid "Plugins Path:"
+msgstr "¿ãâì Ú ßÛÐÓØÝÐÜ:"
+
+#: gui/options.cpp:913
+msgid "Misc"
+msgstr "ÀÐ×ÝÞÕ"
+
+#: gui/options.cpp:915
+msgid "Theme:"
+msgstr "ÂÕÜÐ:"
+
+#: gui/options.cpp:919
+msgid "GUI Renderer:"
+msgstr "ÀÐáâÕàØ×ÐâÞà GUI:"
+
+#: gui/options.cpp:925
+msgid "Autosave:"
+msgstr "°ÒâÞáÞåàÐÝÕÝØÕ:"
+
+#: gui/options.cpp:933
+msgid "Keys"
+msgstr "ºÛÐÒØèØ"
+
+#: gui/options.cpp:940
+msgid "GUI Language:"
+msgstr "Ï×ëÚ ØÝâÕàäÕÙáÐ:"
+
+#: gui/options.cpp:940
+msgid "Language of ScummVM GUI"
+msgstr "Ï×ëÚ ÓàÐäØçÕáÚÞÓÞ ØÝâÕàäÕÙáÐ ScummVM"
+
+#: gui/options.cpp:945
+msgid "English"
+msgstr "English"
+
+#: gui/options.cpp:1089
+msgid "You have to restart ScummVM to take the effect."
+msgstr "²ë ÔÞÛÖÝë ßÕàÕ×ÐßãáâØâì ScummVM çâÞÑë ßàØÜÕÝØâì Ø×ÜÕÝÕÝØï."
+
+#: gui/options.cpp:1102
+msgid "Select directory for savegames"
+msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî ÔÛï áÞåàÐÝÕÝØÙ"
+
+#: gui/options.cpp:1109
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr "½Õ ÜÞÓã ßØáÐâì Ò ÒëÑàÐÝÝãî ÔØàÕÚâÞàØî. ¿ÞÖÐÛãÙáâÐ, ãÚÐÖØâÕ ÔàãÓãî."
+
+#: gui/options.cpp:1118
+msgid "Select directory for GUI themes"
+msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî ÔÛï âÕÜ GUI"
+
+#: gui/options.cpp:1128
+msgid "Select directory for extra files"
+msgstr "²ëÑÕàØâÕ ÔØàÕÚâÞàØî á ÔÞßÞÛÝØâÕÛìÝëÜØ äÐÙÛÐÜØ"
+
+#: gui/options.cpp:1139
+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:337
+msgid "Disabled GFX"
+msgstr "±Õ× ÓàÐäØÚØ"
+
+#: gui/ThemeEngine.cpp:338
+msgid "Standard Renderer (16bpp)"
+msgstr "ÁâÐÝÔÐàâÝëÙ àÐáâÕàØ×ÐâÞà (16bpp)"
+
+#: gui/ThemeEngine.cpp:340
+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..6fe4989982
--- /dev/null
+++ b/po/scummvm.pot
@@ -0,0 +1,1341 @@
+# 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-12 17:44+0200\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"
+"Language: \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:266 gui/massadd.cpp:95 gui/options.cpp:972
+#: 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:102 backends/keymapper/remap-dialog.cpp:54
+msgid "Close"
+msgstr ""
+
+#: gui/GuiManager.cpp:105
+msgid "Mouse click"
+msgstr ""
+
+#: gui/GuiManager.cpp:108 base/main.cpp:285
+msgid "Display keyboard"
+msgstr ""
+
+#: gui/GuiManager.cpp:111 base/main.cpp:288
+msgid "Remap keys"
+msgstr ""
+
+#: gui/KeysDialog.cpp:44
+msgid "Map"
+msgstr ""
+
+#: gui/KeysDialog.cpp:45 gui/launcher.cpp:267 gui/launcher.cpp:873
+#: gui/launcher.cpp:877 gui/massadd.cpp:92 gui/options.cpp:973
+#: 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:170
+msgid "Game"
+msgstr ""
+
+#: gui/launcher.cpp:173
+msgid "ID:"
+msgstr ""
+
+#: gui/launcher.cpp:173 gui/launcher.cpp:174
+msgid ""
+"Short game identifier used for referring to savegames and running the game "
+"from the command line"
+msgstr ""
+
+#: gui/launcher.cpp:177
+msgid "Name:"
+msgstr ""
+
+#: gui/launcher.cpp:177 gui/launcher.cpp:178
+msgid "Full title of the game"
+msgstr ""
+
+#: gui/launcher.cpp:181
+msgid "Language:"
+msgstr ""
+
+#: gui/launcher.cpp:181 gui/launcher.cpp:182
+msgid ""
+"Language of the game. This will not turn your Spanish game version into "
+"English"
+msgstr ""
+
+#: gui/launcher.cpp:183 gui/launcher.cpp:194 gui/options.cpp:80
+#: gui/options.cpp:617 gui/options.cpp:627 gui/options.cpp:943
+#: sound/null.cpp:42
+msgid "<default>"
+msgstr ""
+
+#: gui/launcher.cpp:192
+msgid "Platform:"
+msgstr ""
+
+#: gui/launcher.cpp:192 gui/launcher.cpp:193
+msgid "Platform the game was originally designed for"
+msgstr ""
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "Graphics"
+msgstr ""
+
+#: gui/launcher.cpp:204 gui/options.cpp:850 gui/options.cpp:867
+msgid "GFX"
+msgstr ""
+
+#: gui/launcher.cpp:206
+msgid "Override global graphic settings"
+msgstr ""
+
+#: gui/launcher.cpp:213 gui/options.cpp:873
+msgid "Audio"
+msgstr ""
+
+#: gui/launcher.cpp:215
+msgid "Override global audio settings"
+msgstr ""
+
+#: gui/launcher.cpp:223 gui/options.cpp:877
+msgid "Volume"
+msgstr ""
+
+#: gui/launcher.cpp:225
+msgid "Override global volume settings"
+msgstr ""
+
+#: gui/launcher.cpp:232 gui/options.cpp:885
+msgid "MIDI"
+msgstr ""
+
+#: gui/launcher.cpp:234
+msgid "Override global MIDI settings"
+msgstr ""
+
+#: gui/launcher.cpp:244 gui/options.cpp:891
+msgid "Paths"
+msgstr ""
+
+#: gui/launcher.cpp:250
+msgid "Game Path:"
+msgstr ""
+
+#: gui/launcher.cpp:254 gui/options.cpp:904
+msgid "Extra Path:"
+msgstr ""
+
+#: gui/launcher.cpp:254 gui/launcher.cpp:255
+msgid "Specifies path to additional data used the game"
+msgstr ""
+
+#: gui/launcher.cpp:258
+msgid "Save Path:"
+msgstr ""
+
+#: gui/launcher.cpp:258 gui/launcher.cpp:259 gui/options.cpp:898
+#: gui/options.cpp:899
+msgid "Specifies where your savegames are put"
+msgstr ""
+
+#: gui/launcher.cpp:275 gui/launcher.cpp:353 gui/launcher.cpp:398
+#: gui/options.cpp:245 gui/options.cpp:400 gui/options.cpp:486
+#: gui/options.cpp:545 gui/options.cpp:706 gui/options.cpp:902
+#: gui/options.cpp:905 gui/options.cpp:909 gui/options.cpp:996
+#: gui/options.cpp:1002 gui/options.cpp:1008 gui/options.cpp:1016
+#: gui/options.cpp:1040 gui/options.cpp:1044 gui/options.cpp:1050
+#: gui/options.cpp:1057 gui/options.cpp:1156
+msgid "None"
+msgstr ""
+
+#: gui/launcher.cpp:280 gui/launcher.cpp:357
+#: backends/platform/wii/options.cpp:56
+msgid "Default"
+msgstr ""
+
+#: gui/launcher.cpp:391 gui/options.cpp:1150
+msgid "Select SoundFont"
+msgstr ""
+
+#: gui/launcher.cpp:410 gui/launcher.cpp:548
+msgid "Select directory with game data"
+msgstr ""
+
+#: gui/launcher.cpp:428
+msgid "Select additional game directory"
+msgstr ""
+
+#: gui/launcher.cpp:440
+msgid "Select directory for saved games"
+msgstr ""
+
+#: gui/launcher.cpp:459
+msgid "This game ID is already taken. Please choose another one."
+msgstr ""
+
+#: gui/launcher.cpp:500 engines/dialogs.cpp:113
+msgid "~Q~uit"
+msgstr ""
+
+#: gui/launcher.cpp:500
+msgid "Quit ScummVM"
+msgstr ""
+
+#: gui/launcher.cpp:501
+msgid "A~b~out..."
+msgstr ""
+
+#: gui/launcher.cpp:501
+msgid "About ScummVM"
+msgstr ""
+
+#: gui/launcher.cpp:502
+msgid "~O~ptions..."
+msgstr ""
+
+#: gui/launcher.cpp:502
+msgid "Change global ScummVM options"
+msgstr ""
+
+#: gui/launcher.cpp:504
+msgid "~S~tart"
+msgstr ""
+
+#: gui/launcher.cpp:504
+msgid "Start selected game"
+msgstr ""
+
+#: gui/launcher.cpp:507
+msgid "~L~oad..."
+msgstr ""
+
+#: gui/launcher.cpp:507
+msgid "Load savegame for selected game"
+msgstr ""
+
+#: gui/launcher.cpp:511
+msgid "~A~dd Game..."
+msgstr ""
+
+#: gui/launcher.cpp:511
+msgid "Hold Shift for Mass Add"
+msgstr ""
+
+#: gui/launcher.cpp:513
+msgid "~E~dit Game..."
+msgstr ""
+
+#: gui/launcher.cpp:513
+msgid "Change game options"
+msgstr ""
+
+#: gui/launcher.cpp:515
+msgid "~R~emove Game"
+msgstr ""
+
+#: gui/launcher.cpp:515
+msgid "Remove game from the list. The game data files stay intact"
+msgstr ""
+
+#: gui/launcher.cpp:522
+msgid "Search in game list"
+msgstr ""
+
+#: gui/launcher.cpp:526 gui/launcher.cpp:1037
+msgid "Search:"
+msgstr ""
+
+#: gui/launcher.cpp:529 gui/options.cpp:707
+msgid "Clear value"
+msgstr ""
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+msgid "Load game:"
+msgstr ""
+
+#: gui/launcher.cpp:551 engines/dialogs.cpp:117
+#: backends/platform/wince/CEActionsPocket.cpp:263
+#: backends/platform/wince/CEActionsSmartphone.cpp:225
+msgid "Load"
+msgstr ""
+
+#: gui/launcher.cpp:660
+msgid ""
+"Do you really want to run the mass game detector? This could potentially add "
+"a huge number of games."
+msgstr ""
+
+#: gui/launcher.cpp:661 gui/launcher.cpp:810
+#: 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:661 gui/launcher.cpp:810
+#: 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:708
+msgid "ScummVM couldn't open the specified directory!"
+msgstr ""
+
+#: gui/launcher.cpp:720
+msgid "ScummVM could not find any game in the specified directory!"
+msgstr ""
+
+#: gui/launcher.cpp:734
+msgid "Pick the game:"
+msgstr ""
+
+#: gui/launcher.cpp:810
+msgid "Do you really want to remove this game configuration?"
+msgstr ""
+
+#: gui/launcher.cpp:873
+msgid "This game does not support loading games from the launcher."
+msgstr ""
+
+#: gui/launcher.cpp:877
+msgid "ScummVM could not find any engine capable of running the selected game!"
+msgstr ""
+
+#: gui/launcher.cpp:989
+msgid "Mass Add..."
+msgstr ""
+
+#: gui/launcher.cpp:990
+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:614
+msgid "Graphics mode:"
+msgstr ""
+
+#: gui/options.cpp:625
+msgid "Render mode:"
+msgstr ""
+
+#: gui/options.cpp:625 gui/options.cpp:626
+msgid "Special dithering modes supported by some games"
+msgstr ""
+
+#: gui/options.cpp:635
+msgid "Fullscreen mode"
+msgstr ""
+
+#: gui/options.cpp:638
+msgid "Aspect ratio correction"
+msgstr ""
+
+#: gui/options.cpp:638
+msgid "Correct aspect ratio for 320x200 games"
+msgstr ""
+
+#: gui/options.cpp:645
+msgid "Preferred Device:"
+msgstr ""
+
+#: gui/options.cpp:645
+msgid "Music Device:"
+msgstr ""
+
+#: gui/options.cpp:645
+msgid "Specifies preferred sound device or sound card emulator"
+msgstr ""
+
+#: gui/options.cpp:645 gui/options.cpp:646
+msgid "Specifies output sound device or sound card emulator"
+msgstr ""
+
+#: gui/options.cpp:648
+msgid "MT-32 Device:"
+msgstr ""
+
+#: gui/options.cpp:648
+msgid "Specifies default sound device for Roland MT-32/LAPC1/CM32l/CM64 output"
+msgstr ""
+
+#: gui/options.cpp:650
+msgid "GM Device:"
+msgstr ""
+
+#: gui/options.cpp:650
+msgid "Specifies default sound device for General MIDI output"
+msgstr ""
+
+#: gui/options.cpp:682
+msgid "AdLib emulator:"
+msgstr ""
+
+#: gui/options.cpp:682 gui/options.cpp:683
+msgid "AdLib is used for music in many games"
+msgstr ""
+
+#: gui/options.cpp:693
+msgid "Output rate:"
+msgstr ""
+
+#: gui/options.cpp:693 gui/options.cpp:694
+msgid ""
+"Higher value specifies better sound quality but may be not supported by your "
+"soundcard"
+msgstr ""
+
+#: gui/options.cpp:705
+msgid "SoundFont:"
+msgstr ""
+
+#: gui/options.cpp:705 gui/options.cpp:706
+msgid "SoundFont is supported by some audio cards, Fluidsynth and Timidity"
+msgstr ""
+
+#: gui/options.cpp:710
+msgid "Mixed AdLib/MIDI mode"
+msgstr ""
+
+#: gui/options.cpp:710
+msgid "Use both MIDI and AdLib sound generation"
+msgstr ""
+
+#: gui/options.cpp:713
+msgid "True Roland MT-32 (disable GM emulation)"
+msgstr ""
+
+#: gui/options.cpp:713
+msgid ""
+"Check if you want to use your real hardware Roland-compatible sound device "
+"connected to your computer"
+msgstr ""
+
+#: gui/options.cpp:716
+msgid "Enable Roland GS Mode"
+msgstr ""
+
+#: gui/options.cpp:716
+msgid "Turns off General MIDI mapping for games with Roland MT-32 soundtrack"
+msgstr ""
+
+#: gui/options.cpp:719
+msgid "MIDI gain:"
+msgstr ""
+
+#: gui/options.cpp:732
+msgid "Text and Speech:"
+msgstr ""
+
+#: gui/options.cpp:737 gui/options.cpp:743
+msgid "Speech"
+msgstr ""
+
+#: gui/options.cpp:738 gui/options.cpp:744
+msgid "Subtitles"
+msgstr ""
+
+#: gui/options.cpp:739 gui/options.cpp:745
+msgid "Both"
+msgstr ""
+
+#: gui/options.cpp:743
+msgid "Spch"
+msgstr ""
+
+#: gui/options.cpp:744
+msgid "Subs"
+msgstr ""
+
+#: gui/options.cpp:745
+msgid "Show subtitles and play speech"
+msgstr ""
+
+#: gui/options.cpp:749
+msgid "Subtitle speed:"
+msgstr ""
+
+#: gui/options.cpp:761
+msgid "Music volume:"
+msgstr ""
+
+#: gui/options.cpp:768
+msgid "Mute All"
+msgstr ""
+
+#: gui/options.cpp:771
+msgid "SFX volume:"
+msgstr ""
+
+#: gui/options.cpp:771 gui/options.cpp:772
+msgid "Special sound effects volume"
+msgstr ""
+
+#: gui/options.cpp:778
+msgid "Speech volume:"
+msgstr ""
+
+#: gui/options.cpp:898
+msgid "Save Path: "
+msgstr ""
+
+#: gui/options.cpp:901
+msgid "Theme Path:"
+msgstr ""
+
+#: gui/options.cpp:904 gui/options.cpp:905
+msgid "Specifies path to additional data used by all games or ScummVM"
+msgstr ""
+
+#: gui/options.cpp:908
+msgid "Plugins Path:"
+msgstr ""
+
+#: gui/options.cpp:913
+msgid "Misc"
+msgstr ""
+
+#: gui/options.cpp:915
+msgid "Theme:"
+msgstr ""
+
+#: gui/options.cpp:919
+msgid "GUI Renderer:"
+msgstr ""
+
+#: gui/options.cpp:925
+msgid "Autosave:"
+msgstr ""
+
+#: gui/options.cpp:933
+msgid "Keys"
+msgstr ""
+
+#: gui/options.cpp:940
+msgid "GUI Language:"
+msgstr ""
+
+#: gui/options.cpp:940
+msgid "Language of ScummVM GUI"
+msgstr ""
+
+#: gui/options.cpp:945
+msgid "English"
+msgstr ""
+
+#: gui/options.cpp:1089
+msgid "You have to restart ScummVM to take the effect."
+msgstr ""
+
+#: gui/options.cpp:1102
+msgid "Select directory for savegames"
+msgstr ""
+
+#: gui/options.cpp:1109
+msgid "The chosen directory cannot be written to. Please select another one."
+msgstr ""
+
+#: gui/options.cpp:1118
+msgid "Select directory for GUI themes"
+msgstr ""
+
+#: gui/options.cpp:1128
+msgid "Select directory for extra files"
+msgstr ""
+
+#: gui/options.cpp:1139
+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:337
+msgid "Disabled GFX"
+msgstr ""
+
+#: gui/ThemeEngine.cpp:338
+msgid "Standard Renderer (16bpp)"
+msgstr ""
+
+#: gui/ThemeEngine.cpp:340
+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/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/audiostream.cpp b/sound/audiostream.cpp
index ce2c521e5e..a092e6c29d 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() {
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..b76410f8d1 100644
--- a/sound/decoders/aiff.cpp
+++ b/sound/decoders/aiff.cpp
@@ -161,16 +161,21 @@ 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);
+ 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 fb9499e31f..2a92735616 100644
--- a/sound/decoders/flac.cpp
+++ b/sound/decoders/flac.cpp
@@ -229,7 +229,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
}
}
@@ -354,7 +354,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()]);
}
@@ -667,7 +667,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/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 a8ac7784f5..5aeb40c139 100644
--- a/sound/decoders/vorbis.cpp
+++ b/sound/decoders/vorbis.cpp
@@ -34,7 +34,7 @@
#include "sound/audiostream.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..aaff78bf92 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,221 @@ 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;
+
+ for (int i = 0; GUIOMapping[i] || GUIOMapping[i + 1]; i += 2) {
+ if (musicType == GUIOMapping[i] || musicType == (uint32)-1)
+ res |= GUIOMapping[i + 1];
+ }
+
+ return res;
+}
- const char *s = str.c_str();
- int len = 0;
- const MidiDriverDescription *md = s_musicDrivers;
+bool MidiDriver::_forceTypeMT32 = false;
- // Scan for string end or a colon
- while (s[len] != 0 && s[len] != ':')
- len++;
+MusicType MidiDriver::getMusicType(MidiDriver::DeviceHandle handle) {
+ if (_forceTypeMT32)
+ return MT_MT32;
- 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;
+ 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 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++) {
+ if (identifier.equals(d->getCompleteId()) || identifier.equals(d->getCompleteName())) {
+ return d->getHandle();
+ }
+ }
}
- return NULL;
+ return 0;
}
diff --git a/sound/mididrv.h b/sound/mididrv.h
index d7e89dd9ca..5fffd430fb 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;
- static MidiDriver *createMidi(MidiDriverType midiDriver);
+ enum DeviceStringType {
+ kDriverName,
+ kDriverId,
+ kDeviceId
+ };
- static MidiDriverType detectMusicDriver(int flags);
+ 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);
+
+ /** Get the music type matching the given device handle, or MT_AUTO if there is no match. */
+ static MusicType getMusicType(DeviceHandle handle);
+
+ /** 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..d58471765e 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));
@@ -348,7 +352,7 @@ void MidiParser::hangAllActiveNotes() {
for (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/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/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..3823f2fd3d 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;
/**
@@ -63,6 +50,14 @@ public:
* device name (if it isn't the default one) and the name of the driver.
*/
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;
@@ -94,15 +89,18 @@ public:
virtual MusicDevices getDevices() const = 0;
/**
- * Tries to instantiate a MIDI Driver instance based on the settings of
- * the currently active ConfMan target. That is, the MusicPluginObject
- * should query the ConfMan singleton for the device name, port, etc.
+ * Tries to instantiate a MIDI Driver instance based on the device
+ * previously detected via MidiDriver::detectDevice()
*
* @param mididriver Pointer to a pointer which the MusicPluginObject sets
* to the newly create MidiDriver, or 0 in case of an error
+ *
+ * @param dev Pointer to a device to be used then creating the driver instance.
+ * Default value of zero for driver types without devices.
+ *
* @return a Common::Error describing the error which occurred, or kNoError
*/
- virtual Common::Error createInstance(MidiDriver **mididriver) const = 0;
+ virtual Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const = 0;
};
diff --git a/sound/null.cpp b/sound/null.cpp
index 00a5f5e488..556b96c14c 100644
--- a/sound/null.cpp
+++ b/sound/null.cpp
@@ -22,63 +22,41 @@
* $Id$
*/
-#include "sound/musicplugin.h"
-#include "sound/mpu401.h"
+#include "sound/null.h"
-/* NULL driver */
-class MidiDriver_NULL : public MidiDriver_MPU401 {
-public:
- int open() { return 0; }
- void send(uint32 b) { }
-};
+Common::Error NullMusicPlugin::createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle) const {
+ *mididriver = new MidiDriver_NULL();
+ return Common::kNoError;
+}
-// Plugin interface
+MusicDevices NullMusicPlugin::getDevices() const {
+ MusicDevices devices;
+ devices.push_back(MusicDevice(this, "", MT_NULL));
+ return devices;
+}
-class NullMusicPlugin : public MusicPluginObject {
+class AutoMusicPlugin : public NullMusicPlugin {
public:
const char *getName() const {
- return "No music";
+ return _s("<default>");
}
const char *getId() const {
- return "null";
+ return "auto";
}
-
MusicDevices getDevices() const;
- Common::Error createInstance(MidiDriver **mididriver) const;
};
-Common::Error NullMusicPlugin::createInstance(MidiDriver **mididriver) const {
- *mididriver = new MidiDriver_NULL();
-
- return Common::kNoError;
-}
-
-MusicDevices NullMusicPlugin::getDevices() const {
+MusicDevices AutoMusicPlugin::getDevices() const {
MusicDevices devices;
- // TODO: return a different music type?
- devices.push_back(MusicDevice(this, "", MT_GM));
+ devices.push_back(MusicDevice(this, "", MT_AUTO));
return devices;
}
-MidiDriver *MidiDriver_NULL_create() {
- MidiDriver *mididriver;
-
- NullMusicPlugin p;
- p.createInstance(&mididriver);
-
- return mididriver;
-}
-
-#ifdef DISABLE_ADLIB
-MidiDriver *MidiDriver_ADLIB_create() {
- return MidiDriver_NULL_create();
-}
-#endif
-
//#if PLUGIN_ENABLED_DYNAMIC(NULL)
//REGISTER_PLUGIN_DYNAMIC(NULL, PLUGIN_TYPE_MUSIC, NullMusicPlugin);
//#else
+ REGISTER_PLUGIN_STATIC(AUTO, PLUGIN_TYPE_MUSIC, AutoMusicPlugin);
REGISTER_PLUGIN_STATIC(NULL, PLUGIN_TYPE_MUSIC, NullMusicPlugin);
//#endif
diff --git a/sound/null.h b/sound/null.h
new file mode 100644
index 0000000000..d9343701fa
--- /dev/null
+++ b/sound/null.h
@@ -0,0 +1,56 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ */
+
+#ifndef SOUND_NULL_H
+#define SOUND_NULL_H
+
+#include "sound/musicplugin.h"
+#include "sound/mpu401.h"
+#include "common/translation.h"
+
+/* NULL driver */
+class MidiDriver_NULL : public MidiDriver_MPU401 {
+public:
+ int open() { return 0; }
+ void send(uint32 b) { }
+};
+
+
+// Plugin interface
+
+class NullMusicPlugin : public MusicPluginObject {
+public:
+ virtual const char *getName() const {
+ return _s("No music");
+ }
+
+ virtual const char *getId() const {
+ return "null";
+ }
+
+ virtual MusicDevices getDevices() const;
+ Common::Error createInstance(MidiDriver **mididriver, MidiDriver::DeviceHandle = 0) const;
+};
+
+#endif
diff --git a/sound/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/mt32.cpp b/sound/softsynth/mt32.cpp
index 612dce06b0..95263a040d 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"
@@ -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/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..d600ac28f5 100644
--- a/sound/softsynth/sid.cpp
+++ b/sound/softsynth/sid.cpp
@@ -506,7 +506,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/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/tools/convbdf.c b/tools/convbdf.c
index 4341eac2e7..ad0d9d2373 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 {
diff --git a/tools/create_msvc/create_msvc.cpp b/tools/create_msvc/create_msvc.cpp
index a78c9c46a1..71cc35f8e2 100644
--- a/tools/create_msvc/create_msvc.cpp
+++ b/tools/create_msvc/create_msvc.cpp
@@ -838,11 +838,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
diff --git a/tools/credits.pl b/tools/credits.pl
index bff1251f7a..02a42c12cc 100755
--- a/tools/credits.pl
+++ b/tools/credits.pl
@@ -854,6 +854,31 @@ 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();
+ end_section();
begin_section("Websites (design)");
begin_persons();
@@ -922,7 +947,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 +958,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..9dbc5e0fb7
--- /dev/null
+++ b/tools/po2c
@@ -0,0 +1,260 @@
+#!/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 PoMessageEntry *msgs;\n";
+print "};\n\n";
+print "const PoLangEntry _translations[] = {\n";
+
+foreach my $l (keys(%msgs))
+{
+ $header = $msgs{$l}->{""};
+ $header =~ /charset=([^\\]+)/;
+ $charset = $1;
+ print "\t{ \"" . $l . "\", \"" . $charset . "\", _translation_${l} },\n";
+}
+
+print "\t{ 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;
+}
+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